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); }