Page 1 of 1

Custom Gravity

Posted: Mon Jul 31, 2017 12:03 am
by frag.machine
I have a map with a room where I want a different gravity value from the rest. Anything inside this room - players, monsters, grenades, gibs, lava balls, you name it - must be affected, even if the entity comes from another part of the map (ex: teleported). I tried just setting the .gravity field to the entities inside the room, but apparently it only works for players, everything else is forced back to 0 by the engine (FTEQW, by the way - hello there, Spike :P ). Setting the sv_gravity cvar obviously is not an acceptable solution because would affect entities OUTSIDE the room.

Any suggestions ? As I said, I am using FTEQW and I'm OK with a solution that works only on it (I kinda gave up on Darkplaces at least for this project).

Re: Custom Gravity

Posted: Mon Jul 31, 2017 10:57 am
by toneddu2000
in CSQC you could create a custom gravity only for entities with some field.
You could do for example

Code: Select all

pseudocode:
void myroomtriggerfunc()
{
if(other.classname == blah){
other.customgrav = TRUE;
}
}

void CSQC_InputFrame()
{
cycle trough all entities in map or (probably better, because we're inside a room) by radius
if(e.customgrav){
tracebox(e.origin,e.mins,e.maxs,e.origin+e.velocity,0,e);
//here all the crazy stuff you want for gravity..I dunno, probably invert self.velocity_z or add random velocity + rotation..dunno
e.origin = trace_endpos;
}
}
That could be feasible, I guess. Of course I'm talking about a pure csqc game, probably for a ssqc + csqc could be useless because sv physics would always "win" over csqc (but, again, not sure, I've seen somewhere that ssqc physics can be overwritten in csqc..probably with runstandardplayerphysics() but better ask Spike)

Re: Custom Gravity

Posted: Mon Jul 31, 2017 11:29 am
by frag.machine
I hope there is a workaround without resorting to CSQC. Iterating through every entity every frame via QC is doable in SSQC too, but would be extremely inefficient. Hopefully there is some engine side solution that I don't know about... I know both FTEQW and Darkplaces supports custom physics through a QC override of the standard C code but I could use some help.

Re: Custom Gravity

Posted: Mon Jul 31, 2017 12:32 pm
by toneddu2000
I dunno if it's this the one you were talking about but this should be the structure

Code: Select all

void Player_Think()
{
	//all the crazy stuff goes here (you could add here the "if .customgrav field == TRUE block")

	self.nextthink = time + PHYSICS_TIME_UPDATE;
	self.think = Player_Think;
}

void Physics_CustomPhys()
{
	Player_Think();
}

void Player_Init()
{
	player = spawn();
	player.customphysics = Physics_CustomPhys;
	player.nextthink = time +1 ;
	player.think = Player_Think;
}
In this case you would use .think calls instead of CSQC_InputFrame() but I've never managed to succeed with that method

Re: Custom Gravity

Posted: Mon Jul 31, 2017 5:46 pm
by Spike
big oversight on my part. this has presumably been bugged since vanilla.
quakeworld supported .gravity on players, but ignored it on non-players.

the trigger_setgravity in hipnotic explicitly only affects players for some reason, so I never actually noticed that fte could be misbehaving here.

fte revision 5133 should have a fix.



regarding customphysics, thinks are actually dependant upon movetypes (eg: movetype_push uses self.ltime instead of time). the .customphysics extension reflects this by requiring the qc itself to call the think function.
Anyway, because it got mentioned, here's a somewhat lame example of it.

Code: Select all

void() MyCustomMovetype_Bounce =
{
  if(self.nextthink && time > self.nextthink) // you could even make it into a loop, if you're paranoid about framerate slippage.
  {
    self.nextthink = 0;
    self.think();
  }
  if (self.flags & FL_ONGROUND)
    return; //no need to do anything
  self.velocity_z -= self.gravity * autocvar_sv_gravity * frametime; //apply lame gravity
  traceline(self.origin, self.origin + self.velocity * frametime, FALSE, self); //figure out where we go
  self.velocity -= (self.velocity * trace_plane_normal) * trace_plane_normal * 1.5; //bounce off what we hit. use *1 to just slide. *2 to retain full speed.
  if (trace_fraction < 1 && trace_plane_normal_z > 0.7 && vlen(self.velocity) < 60)
  { //looks like we hit the floor, and we're not travelling fast enough to bounce much.
    self.flags |= FL_ONGROUND; //stop using tracelines and all this extra logic.
    self.velocity = '0 0 0';
    self.groundentity = trace_ent;
  }
  local float frac  = trace_fraction; //touchtriggers can call trigger touches and they can call traceline...
  local entity touchee = trace_ent;
  touchtriggers(self, trace_endpos); //and actually moves there like setorigin and update pvs stuff, but also at the same time checks for triggers (like trigger_setgravity) then calls their touch functions.
  if (frac < 1)
  {
    if (self.touch)
    { //we touched something, maybe world
      other = touchee ;
      self.touch();
    }
    if (trace_ent.touch)
    { //touching is mutual.
      other = self;
      self = touchee ;
      self.touch();
    }
  }
};
anyway, you get the idea. if you want to be complete you need to get complex, and often you can skip parts of it, but whatever.

Re: Custom Gravity

Posted: Mon Jul 31, 2017 7:36 pm
by frag.machine
Thanks Spike! I'll check it when available.
EDIT: yup, now .gravity worked as expected. Thanks again Spike!