c_move(ENTITY* entity,VECTOR* reldist,VECTOR* absdist,var mode)

Moves an entity over a certain distance while performing collision detection, triggering collision events, and gliding along obstacles.

The first vector reldist gives a relative distance and direction in rotated entity coordinates, i.e. the direction that the entity is facing. The second vector absdist gives an absolute distance and direction in world coordinates. The resulting movement is a combination of both distances. Normally the first vector is used for the propelling speed of the entity, and the second one for external forces, like gravity and drift. To zero one of these vectors, the predefined nullvector can be given.

The function returns the amount of distance covered. If the entity could not move at all due to being blocked by obstacles, it returns a negative value or 0. If collision events are enabled, they are triggered for the entity as well as for the obstacle. During a collision event, several predefined variables are set to indicate the type of collision (see below). They can be evaluated in the event function for setting collision or ricocheting behavior of any kind.

Parameters:

entity Entity to be moved.
reldist Move distance vector in entity coordinates
absdist Move distance vector in world coordinates
mode Collision mode, see below.

The following mode flags can be combined:

IGNORE_YOU Ignores the you entity on collision detection (see remark).
IGNORE_FLAG2 A7.10 Ignores all entities with FLAG2 set.
IGNORE_PASSABLE Ignores all passable blocks and entities.
IGNORE_PASSENTS Ignores passable model and sprite entities, but still detects water entities (rectangular passable maps, or passable terrain). It sets the predefined flags in_passable and on_passable . The predefined passable_ent pointer is set to the detected water entity. This can be used, for example, to switch the player behavior to swimming.
IGNORE_WORLD Ignores all level blocks and terrains.
IGNORE_MAPS Ignores all map entities.
IGNORE_MODELS Ignores all models.
IGNORE_SPRITES Ignores all sprites.
IGNORE_PUSH Ignores all entities with lower push or same group values than the given entity, and triggers the EVENT_PUSH collision event on those entities. For ignoring several groups, call c_ignore before c_move.
IGNORE_CONTENT Ignores the content of the move origin. The function is faster, but water entities (see above) are not detected.
ACTIVATE_TRIGGER Enables EVENT_TRIGGER during the motion. Can be slow.
ACTIVATE_PUSH A7.10 Triggers the EVENT_PUSH collision event on the hit entity, regardless of the push or group value. If the event function returns 1, the hit entity is considered an obstacle; if the event function returns 0, it is ignored. This way individual collision groups can be defined.
ACTIVATE_SHOOT A7.10 Enables EVENT_SHOOT triggering of the hit entity, and prevents all other collision events. This flag lets c_move behave similar to c_trace.
ACTIVATE_SONAR A7.10 Enables EVENT_SONAR triggering of the hit entity, and prevents all other collision events. This flag lets c_move behave similar to c_trace.
USE_POLYGON Uses a polygonal hull of all target entities even if their POLYGON flag is not set.
GLIDE Glides along walls and entities on impact.

Depends on:

c_ignore Exclude entity groups from collision detection.
move_friction Friction factor for gliding along walls.
move_min_z Maximum step height (OBB only).
disable_z_glide Disables gliding up slopes (OBB only).

Returns:

 > 0 Distance covered.
<= 0 Entity could not be moved, f.i. due to obstacles.

Modifies:

entity.x, y, z Entity position.
hit.x Position of one of the the collision contacts (there can be several).
hit.nx Normal vector of one of the colliding surfaces.
hit.flags The HIT_TARGET macro is nonzero when something was hit.
in_passable
Set to nonzero when the starting or ending point is inside a water entity.
on_passable Set to nonzero when the hit target is a water entity.
passable_ent When in_passable or on_passable is set, this pointer is set to the detected water terrain (OBB system only).
event_type Type of event when one was triggered.

Remarks:

Speed:

Slow

Example (lite-C):

// simple function for walking over ground
// control the player with the WASD keys
// player origin must be at the model center
// bounding box must be smaller than the player!
action player_walk()
{ 
// if the entity has a non standard size, make sure that the bounding box does not drag along the floor
   if ((my.eflags&FAT) && (my.eflags&NARROW)) // when FAT+NARROW are both set
 		my.min_z *= 0.5;

   var speed_down = 0;   // downward speed by gravity
   var anim_percent = 0; // animation percentage
   VECTOR vFeet;
   vec_for_min(vFeet,me); // vFeet.z = distance from player origin to lowest vertex

   while (1)
   {
// rotate the player using the [A] and [D] keys      
      my.pan += 5*(key_a-key_d)*time_step; 

// determine the ground distance by a downwards trace
      var dist_down; 
      if (c_trace(my.x,vector(my.x,my.y,my.z-5000),IGNORE_ME | IGNORE_PASSABLE | USE_BOX) > 0)
         dist_down = my.z + vFeet.z - target.z; // get distance between player's feet and the ground
      else
         dist_down = 0;

// apply gravity when the player is in the air
      if (dist_down > 0)  // above floor, fall down with increasing speed
         dist_down = clamp(dist_down,0,accelerate(speed_down,5,0.1));
      else                // on or below floor, set downward speed to zero
         speed_down = 0;

// move the player using the [W] and [S] keys      
      var dist_ahead = 5*(key_w-key_s)*time_step;
      dist_ahead = sign(dist_ahead)*(abs(dist_ahead) + 0.5*dist_down); // adapt the speed on slopes
      c_move(me,vector(dist_ahead,0,0),vector(0,0,-dist_down),IGNORE_PASSABLE | GLIDE); // move the player

// animate the player according to its moved distance
      if (dist_ahead != 0) // player is moving ahead
      {
         anim_percent += 1.3*dist_ahead; // 1.3 = walk cycle percentage per quant
         ent_animate(me,"walk",anim_percent,ANM_CYCLE); // play the "walk" animation
      }
      else // player stands still
      { 
         anim_percent += 5*time_step; 
         ent_animate(me,"stand",anim_percent,ANM_CYCLE); // play the "stand" animation
      }
      wait(1);
   }
}

See also:

c_rotate, c_trace, c_scan, c_ignore, move_min_z, move_friction, collisions, model animation, pXent_move

► latest version online