333 lines
11 KiB
C
333 lines
11 KiB
C
|
|
void ent_position(entity_t *ent, double x, double y, double z) {
|
|
ent->last_x = ent->pos_x = x;
|
|
ent->last_y = ent->pos_y = y;
|
|
ent->last_z = ent->pos_z = z;
|
|
AABB_SET(ent->box, x - (ent->width / 2.0), y, z - (ent->width / 2.0), x + (ent->width / 2.0), y + ent->height, z + (ent->width / 2.0));
|
|
}
|
|
|
|
void ent_angle(entity_t *ent, float yaw, float pitch) {
|
|
ent->yaw = yaw;
|
|
ent->pitch = pitch;
|
|
ent->rot_yaw = ((double)yaw) - 90.0;
|
|
}
|
|
|
|
void ent_pos(entity_t *ent, double x, double y, double z, float yaw, float pitch) {
|
|
ent_position(ent, x, y, z);
|
|
ent_angle(ent, yaw, pitch);
|
|
}
|
|
|
|
void ent_init(entity_t *ent, world_t *world, double x, double y, double z, float yaw, float pitch) {
|
|
memset(ent, 0, sizeof(entity_t));
|
|
ent->world = world;
|
|
ent->speed = 1.0;
|
|
ent->eye = 1.8;
|
|
ent->width = 0.6;
|
|
ent->height = 2.0;
|
|
ent->step_height = 0.6;
|
|
ent->jump_motion = 0.42;
|
|
ent->fly_base_speed = 0.05;
|
|
ent->walk_base_speed = 0.1;
|
|
ent->air_base_speed = 0.02;
|
|
ent->first_tick = 1;
|
|
ent_pos(ent, x, y, z, yaw, pitch);
|
|
}
|
|
|
|
void ent_position_vec(entity_t *ent, vec3 pos) {
|
|
ent_position(ent, pos[0], pos[1], pos[2]);
|
|
}
|
|
|
|
void ent_position_eye(entity_t *ent, vec3 pos) {
|
|
ent_position(ent, pos[0], pos[1] - ent->eye, pos[2]);
|
|
}
|
|
|
|
void ent_getpos(entity_t *ent, vec3 pos) {
|
|
VEC3_SET(pos, ent->pos_x, ent->pos_y, ent->pos_z);
|
|
}
|
|
|
|
void ent_geteye(entity_t *ent, vec3 pos) {
|
|
VEC3_SET(pos, ent->pos_x, ent->pos_y + ent->eye, ent->pos_z);
|
|
}
|
|
|
|
void ent_angle_cam(entity_t *ent, camera_t *cam) {
|
|
ent_angle(ent, cam->yaw, cam->pitch);
|
|
}
|
|
|
|
void ent_tick(entity_t *ent) {
|
|
float strafe, forward;
|
|
byte jumping, noclip;
|
|
double last_mot_y, velo, friction, mot;
|
|
double x, y, z;
|
|
// double cx, cy, cz;
|
|
noclip = (ent == ent->world->entity) && ent->world->noclip && !(ent->world->camonly);
|
|
if(noclip)
|
|
ent->ground = 0;
|
|
ent->last_x = ent->pos_x;
|
|
ent->last_y = ent->pos_y;
|
|
ent->last_z = ent->pos_z;
|
|
ent->first_tick = 0;
|
|
if(!(ent->sprinting) && !(ent->sneak) && (ent->forward > 0.0) && /* wld.can_sprint && */ !(ent->use) && ent->sprint)
|
|
ent->sprinting = 1;
|
|
if(ent->sprinting && (ent->sneak || (ent->forward <= 0.0) || ent->use || ent->collided_h /* || !(wld.can_sprint) */))
|
|
ent->sprinting = 0;
|
|
// if(wld.can_fly) {
|
|
if(noclip) {
|
|
if(!(ent->flying))
|
|
ent->flying = 1;
|
|
}
|
|
else if(!(ent->last_jump) && ent->jump) {
|
|
if(ent->fly_timer == 0) {
|
|
ent->fly_timer = 7;
|
|
}
|
|
else {
|
|
ent->flying ^= 1;
|
|
ent->fly_timer = 0;
|
|
}
|
|
}
|
|
// }
|
|
ent->last_jump = ent->jump;
|
|
if(ent->flying && (ent == ent->world->entity)) {
|
|
if(ent->sneak)
|
|
ent->motion_y -= ent->fly_speed * 3.0 * (ent->sprint ? 2.0 : 1.0);
|
|
if(ent->jump)
|
|
ent->motion_y += ent->fly_speed * 3.0 * (ent->sprint ? 2.0 : 1.0);
|
|
}
|
|
if (ent->fly_timer > 0)
|
|
ent->fly_timer -= 1;
|
|
if (ent->jump_ticks > 0)
|
|
ent->jump_ticks -= 1;
|
|
if(fabs(ent->motion_x) < 0.005)
|
|
ent->motion_x = 0.0;
|
|
if(fabs(ent->motion_y) < 0.005)
|
|
ent->motion_y = 0.0;
|
|
if(fabs(ent->motion_z) < 0.005)
|
|
ent->motion_z = 0.0;
|
|
if(ent->blocked) {
|
|
jumping = 0;
|
|
strafe = 0.0;
|
|
forward = 0.0;
|
|
}
|
|
else if(ent == ent->world->entity) {
|
|
strafe = ent->strafe * (ent->sneak ? 0.3 : 1.0) * (ent->use ? 0.2 : 1.0);
|
|
forward = ent->forward * (ent->sneak ? 0.3 : 1.0) * (ent->use ? 0.2 : 1.0);
|
|
jumping = ent->jump;
|
|
}
|
|
if(jumping) {
|
|
if(ent->ground && ent->jump_ticks == 0) {
|
|
ent->motion_y = ent->jump_motion;
|
|
if(ent->sprinting) {
|
|
double bmot = ent->rot_yaw * M_PI / 180.0;
|
|
ent->motion_x -= sin(bmot) * 0.2;
|
|
ent->motion_z += cos(bmot) * 0.2;
|
|
}
|
|
ent->jump_ticks = 10;
|
|
}
|
|
}
|
|
else {
|
|
ent->jump_ticks = 0;
|
|
}
|
|
strafe *= 0.98;
|
|
forward *= 0.98;
|
|
if(ent->flying) {
|
|
last_mot_y = ent->motion_y;
|
|
ent->air_speed = ent->fly_speed * (ent->sprinting ? 2.0 : 1.0);
|
|
}
|
|
velo = 0.91;
|
|
if(ent->ground) {
|
|
velo *= (1.0 - ent->world->friction) * 0.5 + 0.5;
|
|
friction = ent->walk_speed * 0.16277136 / (velo * velo * velo);
|
|
}
|
|
else {
|
|
friction = ent->air_speed;
|
|
}
|
|
mot = strafe * strafe + forward * forward;
|
|
if(mot >= 1.0E-4) {
|
|
mot = sqrt(mot);
|
|
if(mot < 1.0)
|
|
mot = 1.0;
|
|
mot = friction / mot;
|
|
strafe = strafe * mot;
|
|
forward = forward * mot;
|
|
double smot = sin(ent->rot_yaw * M_PI / 180.0);
|
|
double cmot = cos(ent->rot_yaw * M_PI / 180.0);
|
|
ent->motion_x += strafe * cmot - forward * smot;
|
|
ent->motion_z += forward * cmot + strafe * smot;
|
|
}
|
|
velo = 0.91;
|
|
if(ent->ground)
|
|
velo *= (1.0 - ent->world->friction) * 0.5 + 0.5;
|
|
x = ent->motion_x;
|
|
y = ent->motion_y;
|
|
z = ent->motion_z;
|
|
if(noclip) {
|
|
AABB_OFFSET(ent->box, x, y, z)
|
|
ent->pos_x = (ent->box.x1 + ent->box.x2) / 2.0;
|
|
ent->pos_y = ent->box.y1;
|
|
ent->pos_z = (ent->box.z1 + ent->box.z2) / 2.0;
|
|
}
|
|
else {
|
|
double last_x, last_y, last_z;
|
|
bbox_t box;
|
|
bbox_t *list;
|
|
int len;
|
|
byte step;
|
|
if(ent->braked) {
|
|
ent->braked = 0;
|
|
x *= 0.25;
|
|
y *= 0.05000000074505806;
|
|
z *= 0.25;
|
|
ent->motion_x = ent->motion_y = ent->motion_z = 0.0;
|
|
}
|
|
last_x = x;
|
|
last_y = y;
|
|
last_z = z;
|
|
if(ent->ground && ent->sneak) {
|
|
double shift;
|
|
for(shift = 0.05; x != 0.0 && box_get_colliding(ent->world, NULL, box_offset_to(&ent->box, &box, x, -1.0, 0.0)) == 0; last_x = x) {
|
|
if(x < shift && x >= -shift)
|
|
x = 0.0;
|
|
else if(x > 0.0)
|
|
x -= shift;
|
|
else
|
|
x += shift;
|
|
}
|
|
for(; z != 0.0 && box_get_colliding(ent->world, NULL, box_offset_to(&ent->box, &box, 0.0, -1.0, z)) == 0; last_z = z) {
|
|
if(z < shift && z >= -shift)
|
|
z = 0.0;
|
|
else if(z > 0.0)
|
|
z -= shift;
|
|
else
|
|
z += shift;
|
|
}
|
|
for(; x != 0.0 && z != 0.0 && box_get_colliding(ent->world, NULL, box_offset_to(&ent->box, &box, x, -1.0, z)) == 0; last_z = z) {
|
|
if(x < shift && x >= -shift)
|
|
x = 0.0;
|
|
else if(x > 0.0)
|
|
x -= shift;
|
|
else
|
|
x += shift;
|
|
last_x = x;
|
|
if(z < shift && z >= -shift)
|
|
z = 0.0;
|
|
else if(z > 0.0)
|
|
z -= shift;
|
|
else
|
|
z += shift;
|
|
}
|
|
}
|
|
len = box_get_colliding(ent->world, &list, box_add_coord(&ent->box, &box, x, y, z));
|
|
AABB_COPY(ent->box, box);
|
|
for(int n = 0; n < len; n++)
|
|
y = box_calc_yoff(&list[n], &ent->box, y);
|
|
AABB_OFFSET(ent->box, 0.0, y, 0.0);
|
|
step = ent->ground || last_y != y && last_y < 0.0;
|
|
for(int n = 0; n < len; n++)
|
|
x = box_calc_xoff(&list[n], &ent->box, x);
|
|
AABB_OFFSET(ent->box, x, 0.0, 0.0);
|
|
for(int n = 0; n < len; n++)
|
|
z = box_calc_zoff(&list[n], &ent->box, z);
|
|
AABB_OFFSET(ent->box, 0.0, 0.0, z);
|
|
if(ent->step_height > 0.0 && step && (last_x != x || last_z != z)) {
|
|
double step_x = x;
|
|
double step_y = y;
|
|
double step_z = z;
|
|
bbox_t box_prev, box_shift, box_sshift;
|
|
double shift_x, shift_y, shift_z;
|
|
double shift_sx, shift_sy, shift_sz;
|
|
AABB_COPY(ent->box, box_prev);
|
|
AABB_COPY(box, ent->box);
|
|
y = ent->step_height;
|
|
len = box_get_colliding(ent->world, &list, box_add_coord(&ent->box, &box, last_x, y, last_z));
|
|
AABB_COPY(ent->box, box_shift);
|
|
box_add_coord(&box_shift, &box, last_x, 0.0, last_z);
|
|
shift_y = y;
|
|
for(int n = 0; n < len; n++)
|
|
shift_y = box_calc_yoff(&list[n], &box, shift_y);
|
|
AABB_OFFSET(box_shift, 0.0, shift_y, 0.0);
|
|
shift_x = last_x;
|
|
for(int n = 0; n < len; n++)
|
|
shift_x = box_calc_xoff(&list[n], &box_shift, shift_x);
|
|
AABB_OFFSET(box_shift, shift_x, 0.0, 0.0);
|
|
shift_z = last_z;
|
|
for(int n = 0; n < len; n++)
|
|
shift_z = box_calc_zoff(&list[n], &box_shift, shift_z);
|
|
AABB_OFFSET(box_shift, 0.0, 0.0, shift_z);
|
|
AABB_COPY(ent->box, box_sshift);
|
|
shift_sy = y;
|
|
for(int n = 0; n < len; n++)
|
|
shift_sy = box_calc_yoff(&list[n], &box_sshift, shift_sy);
|
|
AABB_OFFSET(box_sshift, 0.0, shift_sy, 0.0);
|
|
shift_sx = last_x;
|
|
for(int n = 0; n < len; n++)
|
|
shift_sx = box_calc_xoff(&list[n], &box_sshift, shift_sx);
|
|
AABB_OFFSET(box_sshift, shift_sx, 0.0, 0.0);
|
|
shift_sz = last_z;
|
|
for(int n = 0; n < len; n++)
|
|
shift_sz = box_calc_zoff(&list[n], &box_sshift, shift_sz);
|
|
AABB_OFFSET(box_sshift, 0.0, 0.0, shift_sz);
|
|
if((shift_x * shift_x + shift_z * shift_z) > (shift_sx * shift_sx + shift_sz * shift_sz)) {
|
|
x = shift_x;
|
|
z = shift_z;
|
|
y = -shift_y;
|
|
AABB_COPY(box_shift, ent->box);
|
|
}
|
|
else {
|
|
x = shift_sx;
|
|
z = shift_sz;
|
|
y = -shift_sy;
|
|
AABB_COPY(box_sshift, ent->box);
|
|
}
|
|
for(int n = 0; n < len; n++)
|
|
y = box_calc_yoff(&list[n], &ent->box, y);
|
|
AABB_OFFSET(ent->box, 0.0, y, 0.0);
|
|
if(step_x * step_x + step_z * step_z >= x * x + z * z) {
|
|
x = step_x;
|
|
y = step_y;
|
|
z = step_z;
|
|
AABB_COPY(box_prev, ent->box);
|
|
}
|
|
}
|
|
ent->pos_x = (ent->box.x1 + ent->box.x2) / 2.0;
|
|
ent->pos_y = ent->box.y1;
|
|
ent->pos_z = (ent->box.z1 + ent->box.z2) / 2.0;
|
|
ent->collided_h = last_x != x || last_z != z;
|
|
ent->collided_v = last_y != y;
|
|
ent->ground = ent->collided_v && last_y < 0.0;
|
|
ent->collided = ent->collided_h || ent->collided_v;
|
|
if(ent->ground) {
|
|
if(ent->fall_distance > 0.0) {
|
|
// fall_distance ...
|
|
ent->fall_distance = 0.0;
|
|
}
|
|
}
|
|
else if(y < 0.0) {
|
|
ent->fall_distance = ent->fall_distance - y;
|
|
}
|
|
if(last_x != x)
|
|
ent->motion_x = 0.0;
|
|
if(last_z != z)
|
|
ent->motion_z = 0.0;
|
|
if(last_y != y)
|
|
ent->motion_y = 0.0;
|
|
}
|
|
ent->motion_y -= ent->world->gravity * 0.1;
|
|
ent->motion_y *= 0.9800000190734863;
|
|
ent->motion_x *= velo;
|
|
ent->motion_z *= velo;
|
|
if(ent->flying)
|
|
ent->motion_y = last_mot_y * 0.6;
|
|
ent->walk_speed = ent->walk_base_speed * ent->speed;
|
|
ent->air_speed = ent->air_base_speed * ent->speed;
|
|
ent->fly_speed = ent->fly_base_speed * ent->speed;
|
|
if(ent->sprinting) {
|
|
ent->air_speed *= 1.3;
|
|
ent->walk_speed *= 1.3;
|
|
}
|
|
if(ent->ground && ent->flying && !noclip)
|
|
ent->flying = 0;
|
|
// cx = ent->world->clamp_xz ? CLAMP_VALUE(ent->pos_x, ent->world->global.box.x1, ent->world->global.box.x2) : ent->pos_x;
|
|
// cy = ent->world->clamp_y ? CLAMP_VALUE(ent->pos_y, ent->world->global.box.y1, ent->world->global.box.y2) : ent->pos_y;
|
|
// cz = ent->world->clamp_xz ? CLAMP_VALUE(ent->pos_z, ent->world->global.box.z1, ent->world->global.box.z2) : ent->pos_z;
|
|
// if(cx != ent->pos_x || cy != ent->pos_y || cz != ent->pos_z)
|
|
// ent_position(ent, cx, cy, cz);
|
|
}
|