Here, a basic player/ gravity code that keeps a distance to the ground:

Code:
///////////////////////////////
#include <acknex.h>
#include <default.c>
///////////////////////////////

var key_space_released = 0;
var gravity_acceleration = 5;

// basic camera code
void camera_update(ENTITY* ent) {
	
	VECTOR temp;

	camera.pan = ent.pan;
	camera.tilt = -5;
	
	vec_set(temp,vector(-100,0,4));
	vec_rotate(temp,camera.pan);
	vec_add(temp,ent.x);
	vec_set(camera.x,temp);

}


action act_player() {
	
	player = me;
	c_setminmax(my);
	set(my,SHADOW | UNLIT);
	my.skill4 = 8; // height above ground, should not be equal or below zero - increase min_z (min_z is negative) instead, if necessary
	
	while(1) {

		// horizontal movement

		my.pan += (key_a-key_d)*10*time_step;
		my.skill1 += ((key_w-key_s)*15 - my.skill1)/4*time_step; // makes player accelerate and stop smoothly
		c_move(me,vector(my.skill1*time_step,0,0),nullvector,GLIDE);


		// vertical movement and gravity

		result = c_trace(my.x,vector(my.x,my.y,my.z-200),IGNORE_ME | IGNORE_PASSABLE | USE_BOX);
		result += !trace_hit*200; // when !trace_hit ist true, c_trace returns 0, that's why we have to add some quants (f.i. the maximum trace distance)
		
		if(trace_hit) my.skill3 = target.z; // see 25 lines below
		else my.skill3 = -9999999;

		if(result > my.skill4 || my.skill2 > 0) {
			
			my.skill2 -= gravity_acceleration*time_step;
			my.skill2 = maxv(my.skill2,-80);
			c_move(me,nullvector,vector(0,0,my.skill2*time_step),GLIDE);
			
		}
		else {
			
			my.skill2 = 0;
			if(key_space) {
				
				if(key_space_released) {
					key_space_released = 0;
					my.skill2 = 35;	// jump strength
				}
				
			}
			else key_space_released = 1; // no infinite jumping, release space (while on ground) for a new jump
			
		}
		
		my.z = maxv(my.z,my.skill3+my.skill4-my.min_z); // make sure player's feet stay above ground
		
		camera_update(my);
		
		wait(1);
	}
	
}

void main() {
	
	fps_max = 60;
	video_mode = 10;
	level_load("tip3.wmb");
	ent_create(CUBE_MDL,nullvector,act_player);
	
}



I don't think I got the vent/ grate part right. In general, it's probably a better idea to set some objects that may be difficult for your player code to handle passable and use simple invisible collision shapes/ models.
When you're working on a shooter, you can use c_ignore and groups instead of the passable flag to still allow polygonal collision on those objects.


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends