784 lines
28 KiB
C
784 lines
28 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
#include <glad/glad.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <cglm/cglm.h>
|
|
|
|
#include "hash.h"
|
|
#include "base.h"
|
|
#include "display.h"
|
|
#include "menus.h"
|
|
#include "proj.h"
|
|
#include "move.h"
|
|
#include "maeth.h"
|
|
#include "entities.h"
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------ //
|
|
double choffx, choffz;
|
|
double choffxE, choffzE;
|
|
|
|
static int nTxts = 0;
|
|
|
|
// necessary condition for 2 boxes to collide (w*w + h*h + d*d is (diagonal length of the cube)²)
|
|
bool is_at_least_somewhat_close(cube_0* c1, cube_0* c2) {
|
|
return (
|
|
distance_pt_pt_3d_sq(c1->x+c1->w/2.0, c1->y+c1->h/2.0, c1->z+c1->d/2.0, (c2->x+choffx)+c2->w/2.0, c2->y+c2->h/2.0, (c2->z+choffz)+c2->d/2.0) <=
|
|
c1->w*c1->w+c1->h*c1->h+c1->d*c1->d + c2->w*c2->w+c2->h*c2->h+c2->d*c2->d
|
|
);
|
|
}
|
|
|
|
bool is_colliding_with_map(cube_0* cb) {
|
|
for(int w = -render_distance; w <= render_distance; w++) {
|
|
for(int h = -render_distance; h <= render_distance; h++) {
|
|
room* rtd = hashtbl_find_opt(visited, player_chx+w, player_chy+h);
|
|
if(rtd != NULL) {
|
|
choffx = 2*room_width*w;
|
|
choffz = 2*room_depth*h;
|
|
for(int k = 0; k < rtd->map_size; k++) {
|
|
if(is_at_least_somewhat_close(cb, rtd->map[k])) {
|
|
for(int d = 0; d < 8; d++) {
|
|
if(distance_pt_cube_0_3d((cb->x-choffx)+cb->w*(d%2==0), cb->y+cb->h*((d/2)%2==0), (cb->z-choffz)+cb->d*((d/4)%2==0), rtd->map[k]) <= 0.001) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool is_colliding_with_tp(cube_0* cb) {
|
|
for(int w = -render_distance; w <= render_distance; w++) {
|
|
for(int h = -render_distance; h <= render_distance; h++) {
|
|
room* rtd = hashtbl_find_opt(visited, player_chx+w, player_chy+h);
|
|
if(rtd != NULL) {
|
|
choffx = 2*room_width*w;
|
|
choffz = 2*room_depth*h;
|
|
for(int k = 0; k < rtd->tps_size; k++) {
|
|
if(is_at_least_somewhat_close(cb, rtd->tps[k]->hitbox)) {
|
|
for(int d = 0; d < 8; d++) {
|
|
if(distance_pt_cube_0_3d(cb->x+cb->w*(d%2==0), cb->y+cb->h*((d/2)%2==0), cb->z+cb->d*((d/4)%2==0), rtd->tps[k]->hitbox) <= 0.001) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool is_colliding_with_ent_sp(cube_0* cb, int allowed) {
|
|
for(int w = -render_distance; w <= render_distance; w++) {
|
|
for(int h = -render_distance; h <= render_distance; h++) {
|
|
room* rtd = hashtbl_find_opt(visited, player_chx+w, player_chy+h);
|
|
if(rtd != NULL) {
|
|
choffx = 2*room_width*w;
|
|
choffz = 2*room_depth*h;
|
|
for(int k = 0; k < rtd->ent_len; k++) {
|
|
if(
|
|
rtd->ents[k]->entity_type == allowed &&
|
|
(cb->x != rtd->ents[k]->pos->x || cb->y != rtd->ents[k]->pos->y || cb->z != rtd->ents[k]->pos->z) &&
|
|
is_at_least_somewhat_close(cb, rtd->ents[k]->pos)
|
|
) {
|
|
for(int d = 0; d < 8; d++) {
|
|
if(distance_pt_cube_0_3d(cb->x+cb->w*(d%2==0), cb->y+cb->h*((d/2)%2==0), cb->z+cb->d*((d/4)%2==0), rtd->ents[k]->pos) <= 0.001) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool is_colliding_with_ent_sp2(cube_0* cb, int allowed1, int allowed2) {
|
|
for(int w = -render_distance; w <= render_distance; w++) {
|
|
for(int h = -render_distance; h <= render_distance; h++) {
|
|
room* rtd = hashtbl_find_opt(visited, player_chx+w, player_chy+h);
|
|
if(rtd != NULL) {
|
|
choffx = 2*room_width*w;
|
|
choffz = 2*room_depth*h;
|
|
for(int k = 0; k < rtd->ent_len; k++) {
|
|
if(
|
|
(rtd->ents[k]->entity_type == allowed1 || rtd->ents[k]->entity_type == allowed2) &&
|
|
(cb->x != rtd->ents[k]->pos->x || cb->y != rtd->ents[k]->pos->y || cb->z != rtd->ents[k]->pos->z) &&
|
|
is_at_least_somewhat_close(cb, rtd->ents[k]->pos)
|
|
) {
|
|
for(int d = 0; d < 8; d++) {
|
|
if(distance_pt_cube_0_3d(cb->x+cb->w*(d%2==0), cb->y+cb->h*((d/2)%2==0), cb->z+cb->d*((d/4)%2==0), rtd->ents[k]->pos) <= 0.001) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------ //
|
|
|
|
// in case some entities escape their chunk
|
|
void update_entity_chunk() {
|
|
if(!is_one_room) {
|
|
for(int w = -render_distance; w <= render_distance; w++) {
|
|
for(int h = -render_distance; h <= render_distance; h++) {
|
|
room* rtd = hashtbl_find_opt(visited, player_chx+w, player_chy+h);
|
|
if(rtd != NULL) {
|
|
for(int k = 0; k < rtd->ent_len; k++) {
|
|
int chdx = (int)(rtd->ents[k]->pos->x/room_width);
|
|
int chdz = (int)(rtd->ents[k]->pos->z/room_depth);
|
|
|
|
if(chdx != 0 || chdz != 0) {
|
|
entity* deld = remove_entity_return(rtd->ents, &rtd->ent_memlen, &rtd->ent_len, k);
|
|
|
|
//printf("(%lf, %lf) -> ", deld->pos->x, deld->pos->z);
|
|
|
|
deld->pos->x -= 2.0*room_width*chdx;
|
|
deld->pos->z -= 2.0*room_depth*chdz;
|
|
|
|
//printf("(%lf, %lf)\n", deld->pos->x, deld->pos->z);
|
|
|
|
room* dest = hashtbl_find_opt(visited, player_chx+w+chdx, player_chy+h+chdz);
|
|
if(dest != NULL) {
|
|
add_entity(dest->ents, &dest->ent_memlen, &dest->ent_len, deld);
|
|
}
|
|
|
|
k -= 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void update_entity(entity* ent, float dtime) {
|
|
(*ent->updatePos)(dtime, ent, ent->pos);
|
|
}
|
|
|
|
void update_entities(float dtime, room* rtd) {
|
|
if(rtd != NULL) {
|
|
for(int k = 0; k < rtd->ent_len; k++) {
|
|
if(rtd->ents[k]->updatePos != NULL) {
|
|
//printf("e\n");
|
|
update_entity(rtd->ents[k], dtime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void update_nearby_entities(float dtime, int render_distance) {
|
|
nTxts = 0;
|
|
for(int w = -render_distance; w <= render_distance; w++) {
|
|
for(int h = -render_distance; h <= render_distance; h++) {
|
|
choffxE = 2*room_width*w;
|
|
choffzE = 2*room_depth*h;
|
|
update_entities(dtime, hashtbl_find_opt(visited, player_chx+w, player_chy+h));
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------ //
|
|
|
|
void speen(float dtime, entity* ent, cube_0* ret) {
|
|
ret->hz_angle += ((double)dtime)*1.5;
|
|
}
|
|
|
|
// metad1 = main proj speed
|
|
// metad2 = shot proj speed
|
|
// metad3 = shot proj freq
|
|
// metad4 = shot proj time to live
|
|
// metad5 = time left before shooting
|
|
void speen2(float dtime, entity* ent, cube_0* ret) {
|
|
ret->hz_angle += ((double)dtime)*ent->metad3;
|
|
ent->metad5 -= (double)dtime;
|
|
if(ent->metad5 <= 0.0) {
|
|
ent->metad5 = ent->metad3;
|
|
double dx = (ret->x+ret->w/2 - (camx-choffxE));
|
|
double dy = (ret->y+ret->h/2 - (camy));
|
|
double dz = (ret->z+ret->d/2 - (camz-choffzE));
|
|
double total = sqrt(dx*dx + dy*dy + dz*dz);
|
|
dx = ent->metad2*dx/total;
|
|
dy = ent->metad2*dy/total;
|
|
dz = ent->metad2*dz/total;
|
|
appendProj(ret->x+ret->w/2+choffxE, ret->y+ret->h/2, ret->z+ret->d/2+choffzE, 0.1, 0.1, 0.1, -dx, -dy, -dz, 0.0, 0.0, 0.0, 255, 0, 0, 10, ent->metad4);
|
|
}
|
|
if(ent->metad1 != 0.0) {
|
|
double dx = (ret->x+ret->w/2 - (camx-choffxE));
|
|
double dy = (ret->y+ret->h/2 - (camy));
|
|
double dz = (ret->z+ret->d/2 - (camz-choffzE));
|
|
double total = sqrt(dx*dx + dy*dy + dz*dz);
|
|
dx = ent->metad1*dx/total;
|
|
dy = ent->metad1*dy/total;
|
|
dz = ent->metad1*dz/total;
|
|
ret->x -= dtime*dx;
|
|
if(is_colliding_with_map(ret) || is_colliding_with_tp(ret)) {
|
|
ret->x += dtime*dx;
|
|
}
|
|
ret->y -= dtime*dy;
|
|
if(is_colliding_with_map(ret) || is_colliding_with_tp(ret)) {
|
|
ret->y += dtime*dy;
|
|
}
|
|
ret->z -= dtime*dz;
|
|
if(is_colliding_with_map(ret) || is_colliding_with_tp(ret)) {
|
|
ret->z += dtime*dz;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// metad{1,2,3} = velocities
|
|
// metad{4,5,6} = accelerations
|
|
// metad7 = cooldown
|
|
// metad8 = ttl
|
|
// metad9 = remaining
|
|
// metai{1,2,3} = 1000*proj_size_{x,y,z}
|
|
// metai4 = dmg
|
|
void gunning(float dtime, entity* ent, cube_0* ret) {
|
|
ent->metad9 -= (double)dtime;
|
|
if(ent->metad9 <= 0.0) {
|
|
ent->metad9 = ent->metad7;
|
|
double psizex = (double)(ent->metai1)/1000.0;
|
|
double psizey = (double)(ent->metai2)/1000.0;
|
|
double psizez = (double)(ent->metai3)/1000.0;
|
|
appendProj(
|
|
ret->x+ret->w/2.0-psizex/2.0, ret->y+ret->h/2.0-psizey/2.0, ret->z+ret->d/2.0-psizez/2.0,
|
|
psizex, psizey, psizez,
|
|
ent->metad1, ent->metad2, ent->metad3,
|
|
ent->metad4, ent->metad5, ent->metad6,
|
|
255, 128, 128,
|
|
ent->metai4, ent->metad8
|
|
);
|
|
}
|
|
}
|
|
|
|
void speen3(float dtime, entity* ent, cube_0* ret) {
|
|
ret->vt_angle += ((double)dtime)*2.5;
|
|
}
|
|
|
|
// metad{1,2,3} = og pos
|
|
// metad{4,5,6} = amplitudes
|
|
// metai1 = frequency multiplier
|
|
// metai2 = frequency divider
|
|
// metai3 = phase
|
|
void moving_xyz(float dtime, entity* ent, cube_0* ret) {
|
|
bool canMove = (ent->metai5 == -1) || xor(buttonSwitch[ent->metai5], (bool)ent->metai4);
|
|
if(canMove) {
|
|
ret->x = ent->metad1 + ent->metad4*cos((double)(ent->metai1*sim_time/ent->metai2 + ent->metai3*3.14159/180.0));
|
|
ret->y = ent->metad2 + ent->metad5*cos((double)(ent->metai1*sim_time/ent->metai2 + ent->metai3*3.14159/180.0));
|
|
ret->z = ent->metad3 + ent->metad6*cos((double)(ent->metai1*sim_time/ent->metai2 + ent->metai3*3.14159/180.0));
|
|
}
|
|
//printf("%lf %lf %lf\n", ret->x, ret->y, ret->z);
|
|
}
|
|
|
|
// metad{1,2,3} = og pos
|
|
// metad{4,5,6} = speed
|
|
// metad{7,8,9} = max_delta
|
|
// metai1 = ret->x_side (+/- 1)
|
|
// metai2 = ret->y_side (+/- 1)
|
|
// metai3 = ret->z_side (+/- 1)
|
|
void moving_xyz_line(float dtime, entity* ent, cube_0* ret) {
|
|
bool canMove = (ent->metai5 == -1) || xor(buttonSwitch[ent->metai5], (bool)ent->metai4);
|
|
if(canMove) {
|
|
ret->x += (ent->metai1)*ent->metad4*dtime;
|
|
if(absf(ent->metad1 - ret->x) > ent->metad7) {
|
|
//printf("-x-\n");
|
|
ent->metai1 *= (-1);
|
|
ret->x += (ent->metai1)*ent->metad4*dtime;
|
|
}
|
|
|
|
ret->y += (ent->metai2)*ent->metad5*dtime;
|
|
if(absf(ent->metad2 - ret->y) > ent->metad8) {
|
|
//printf("-y-\n");
|
|
ent->metai2 *= (-1);
|
|
ret->y += (ent->metai2)*ent->metad5*dtime;
|
|
}
|
|
|
|
ret->z += (ent->metai3)*ent->metad6*dtime;
|
|
if(absf(ent->metad3 - ret->z) > ent->metad9) {
|
|
//printf("-z-\n");
|
|
ent->metai3 *= (-1);
|
|
ret->z += (ent->metai3)*ent->metad6*dtime;
|
|
}
|
|
}
|
|
}
|
|
|
|
// metai1 = id of the interface
|
|
// metai2 = price
|
|
// metai3 = doPay
|
|
// metach1 = text (stored here to free() easily)
|
|
void subtitle_text_box_far(float dtime, entity* ent, cube_0* ret) {
|
|
if(distance_pt_cube_0_3d_infinite(camx-choffxE, camy, camz-choffzE, ret) <= 3.0) {
|
|
gl_drawString(fShader, ent->metach1, 0.0f, -0.7f+0.12f*nTxts, 0.03f, ret->red, ret->green, ret->blue, 0.003f, 0);
|
|
nTxts+=1;
|
|
}
|
|
}
|
|
|
|
// metai1 = id of the interface
|
|
// metai2 = price
|
|
// metai3 = doPay
|
|
// metach1 = text (stored here to free() easily)
|
|
void subtitle_text_box(float dtime, entity* ent, cube_0* ret) {
|
|
if(distance_pt_cube_0_3d_infinite(camx+player_chx*room_width*2, camy, camz+player_chy*room_depth*2, ret) <= 1.5) {
|
|
gl_drawString(fShader, ent->metach1, 0.0f, -0.7f+0.12f*nTxts, 0.03f, ret->red, ret->green, ret->blue, 0.003f, 0);
|
|
nTxts+=1;
|
|
}
|
|
}
|
|
|
|
// metad1 = time ON
|
|
// metad2 = time OFF
|
|
// metad3 = current time left
|
|
// metai1 = 0 if OFF, 1 if ON
|
|
void beating_block(float dtime, entity* ent, cube_0* ret) {
|
|
ent->metad3 -= dtime;
|
|
if(ent->metad3 <= 0.0) {
|
|
if(ent->metai1) {
|
|
ent->metad3 = ent->metad2;
|
|
} else {
|
|
ent->metad3 = ent->metad1;
|
|
}
|
|
ent->metai1 = 1-ent->metai1;
|
|
}
|
|
}
|
|
|
|
// metad1 = hz_speed
|
|
// metad2 = vt_speed
|
|
void spinning_platform(float dtime, entity* ent, cube_0* ret) {
|
|
ret->hz_angle += ent->metad1*dtime;
|
|
ret->vt_angle += ent->metad2*dtime;
|
|
}
|
|
|
|
// metai1 = default state
|
|
// metad1 = remaining time
|
|
// metad2 = activation time
|
|
void math_block(float dtime, entity* ent, cube_0* ret) {
|
|
if(ent->metad1 > -0.9) {
|
|
ent->metad1 = maxd(ent->metad1 - (double)dtime, 0.0);
|
|
}
|
|
if(mathResult == FAILURE && ent->metad1 != 0.0) {
|
|
ent->metad1 = 0.0;
|
|
//mathResult = IDLE;
|
|
}
|
|
}
|
|
|
|
// metad1 = hz_speed (// to ret->y)
|
|
// metad2 = vt_speed (// to ret->x)
|
|
// metad7 = norm of HZ deviation
|
|
// metad8 = norm of VT deviation
|
|
// metai1 = dps
|
|
void lava_postStep(float dtime, entity* ent, cube_0* ret) {
|
|
ret->hz_angle += ((double)dtime)*ent->metad1;
|
|
ret->vt_angle += ((double)dtime)*ent->metad2;
|
|
|
|
ret->x = ent->metad4+(ent->metad7)*cos(ret->hz_angle);
|
|
ret->y = ent->metad5+(ent->metad8)*sin(ret->vt_angle);
|
|
ret->z = ent->metad6+(ent->metad7)*sin(ret->hz_angle)+(ent->metad8)*cos(ret->vt_angle);
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
/*ret->hz_angle -= ((double)dtime)*ent->metad1;
|
|
ret->vt_angle -= ((double)dtime)*ent->metad2;
|
|
|
|
ret->x = ent->metad4+(ent->metad7)*cos(ret->hz_angle);
|
|
ret->y = ent->metad5+(ent->metad8)*sin(ret->vt_angle);
|
|
ret->z = ent->metad6+(ent->metad7)*sin(ret->hz_angle)+(ent->metad8)*cos(ret->vt_angle);*/
|
|
//printf("DDDD\n");
|
|
movingPlatformUpdate = ent;
|
|
doUpdateMoving = true;
|
|
}
|
|
}
|
|
|
|
// metad1 = vx
|
|
// metad2 = vy
|
|
// metad3 = vz
|
|
// metad4 = friction
|
|
// metad5 = mass (kg)
|
|
void movableCrate_postStep(float dtime, entity* ent, cube_0* ret) {
|
|
if(ret->y < -48) {
|
|
*(ent->hitpoints) = 0;
|
|
} else {
|
|
//printf("(%lf %lf %lf)\n", ent->metad1, ent->metad2, ent->metad3);
|
|
|
|
// --P->
|
|
ent->metad2 += -((double)dtime)*(gravity_factor*ent->metad5);
|
|
|
|
ret->x += dtime*ent->metad1;
|
|
if(
|
|
absf(ent->metad1) < 0.04 ||
|
|
is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp(ret, 10) ||
|
|
distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist
|
|
) {
|
|
ret->x -= dtime*ent->metad1;
|
|
ent->metad1 = 0.0;
|
|
}
|
|
ret->y += dtime*ent->metad2;
|
|
if(
|
|
absf(ent->metad2) < 0.04 ||
|
|
is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp(ret, 10) ||
|
|
distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist
|
|
) {
|
|
ret->y -= dtime*ent->metad2;
|
|
ent->metad2 = 0.0;
|
|
}
|
|
ret->z += dtime*ent->metad3;
|
|
if(
|
|
absf(ent->metad3) < 0.04 ||
|
|
is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp(ret, 10) ||
|
|
distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist
|
|
) {
|
|
ret->z -= dtime*ent->metad3;
|
|
ent->metad3 = 0.0;
|
|
}
|
|
|
|
ent->metad1 *= (1.0 - ent->metad4*((double)(dtime)));
|
|
ent->metad2 *= (1.0 - ent->metad4*((double)(dtime)));
|
|
ent->metad3 *= (1.0 - ent->metad4*((double)(dtime)));
|
|
}
|
|
}
|
|
|
|
// metai1 = button freq
|
|
// metai2 = is triggered (0/1)
|
|
void movCrateButton_postStep(float dtime, entity* ent, cube_0* ret) {
|
|
bool isIn = false;
|
|
for(int k = 0; k < current_room->ent_len*(1-isIn); k++) {
|
|
for(int d = 0; d < 8*(1-isIn); d++) {
|
|
if(
|
|
current_room->ents[k]->entity_type == 10 &&
|
|
distance_pt_cube_0_3d(ret->x+ret->w*(d%2==0), ret->y+ret->h*((d/2)%2==0), ret->z+ret->d*((d/4)%2==0), current_room->ents[k]->pos) <= 0.001
|
|
) {
|
|
isIn = true;
|
|
ent->metai2 = 1;
|
|
if(!buttonSwitch[ent->metai1]) {
|
|
//printf("In %d\n", ent->metai1);
|
|
buttonSwitch[ent->metai1] = true;
|
|
buttonTimes[ent->metai1] = -1.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(!isIn && ent->metai2 != 0) {
|
|
ent->metai2 = 0;
|
|
buttonSwitch[ent->metai1] = false;
|
|
}
|
|
}
|
|
|
|
void entity1_onHit(entity* ent, cube_0* ret) {
|
|
pt_2d direct = (pt_2d){.x = camx - ret->x-ret->w/2.0, .y = camy - ret->y-ret->h/2.0, .z = camz - ret->z-ret->d/2.0};
|
|
if(direct.x*direct.x + direct.y*direct.y + direct.z*direct.z >= 0.00001) {
|
|
normalize(&direct);
|
|
outvx = direct.x * ent->metad4;
|
|
//outvy = direct.y * ent->metad4;
|
|
outvz = direct.z * ent->metad4;
|
|
}
|
|
}
|
|
// metad1 = speed
|
|
// metad2 = jump height
|
|
// metad3 = vertical speed
|
|
// metad4 = knockback on hit (for player) [speed]
|
|
// metai1 = damage
|
|
// metai2 = isActivated (0/1)
|
|
// metai3 = trigger button (-1 if none)
|
|
void enemy1_postStep(float dtime, entity* ent, cube_0* ret) {
|
|
if(ent->metai2) {
|
|
double dx = (camx - choffxE)-ret->x-ret->w/2.0;
|
|
ent->metad3 -= gravity_factor*dtime;
|
|
double dz = (camz - choffzE)-ret->z-ret->d/2.0;
|
|
double norm = sqrt(dx*dx + dz*dz);
|
|
dx = ent->metad1*dx/norm;
|
|
dz = ent->metad1*dz/norm;
|
|
|
|
bool hasCollisionXZ = false;
|
|
bool hasCollisionY = false;
|
|
|
|
ret->x += dtime*dx;
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
ret->x -= dtime*dx;
|
|
player_hp -= ent->metai1;
|
|
entity1_onHit(ent, ret);
|
|
} else if(is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp2(ret, 10, 16)) {
|
|
ret->x -= dtime*dx;
|
|
hasCollisionXZ = true;
|
|
}
|
|
|
|
ret->z += dtime*dz;
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
ret->z -= dtime*dz;
|
|
player_hp -= ent->metai1;
|
|
entity1_onHit(ent, ret);
|
|
} else if(is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp2(ret, 10, 16)) {
|
|
ret->z -= dtime*dz;
|
|
hasCollisionXZ = true;
|
|
}
|
|
|
|
ret->y += dtime*ent->metad3;
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
ret->y -= dtime*ent->metad3;
|
|
player_hp -= ent->metai1;
|
|
entity1_onHit(ent, ret);
|
|
ent->metad3 = 0.0;
|
|
} else if(is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp2(ret, 10, 16)) {
|
|
ret->y -= dtime*ent->metad3;
|
|
hasCollisionY = hasCollisionY || (ent->metad3 <= 0.0);
|
|
ent->metad3 = 0.0;
|
|
}
|
|
|
|
if(hasCollisionXZ && hasCollisionY) {
|
|
ent->metad3 += sqrt(2.0*gravity_factor*ent->metad2);
|
|
//printf("%lf\n", ent->metad3);
|
|
}
|
|
|
|
if(ret->y <= -48.0) {
|
|
*(ent->hitpoints) = 0;
|
|
}
|
|
} else if((choffxE == 0 && choffzE == 0) || (ent->metai3 != -1 && buttonSwitch[ent->metai3])) {
|
|
ent->metai2 = 1;
|
|
}
|
|
}
|
|
|
|
void entity2_onHit(entity* ent, cube_0* ret) {
|
|
pt_2d direct = (pt_2d){.x = camx - ret->x-ret->w/2.0, .y = camy - ret->y-ret->h/2.0, .z = camz - ret->z-ret->d/2.0};
|
|
if(direct.x*direct.x + direct.y*direct.y + direct.z*direct.z >= 0.00001) {
|
|
normalize(&direct);
|
|
outvx = direct.x * ent->metad3;
|
|
//outvy = direct.y * ent->metad4;
|
|
outvz = direct.z * ent->metad3;
|
|
}
|
|
}
|
|
// metad1 = speed
|
|
// metad2 = jump height
|
|
// metad3 = knockback on hit (for player) [speed]
|
|
// metad4 = knockback on hit (for entity) [speed]
|
|
// metad{5,6,7} = {x,y,z} speed
|
|
// metai1 = damage
|
|
// metai2 = isActivated (0/1)
|
|
// metai3 = trigger button (-1 if none)
|
|
void enemy2_postStep(float dtime, entity* ent, cube_0* ret) {
|
|
if(ent->metai2) {
|
|
double dx = (camx - choffxE)-ret->x-ret->w/2.0;
|
|
double dz = (camz - choffzE)-ret->z-ret->d/2.0;
|
|
double norm = sqrt(dx*dx + dz*dz);
|
|
dx = ent->metad1*dx/norm;
|
|
dz = ent->metad1*dz/norm;
|
|
|
|
ent->metad5 += dx*dtime;
|
|
ent->metad6 -= gravity_factor*dtime;
|
|
ent->metad7 += dz*dtime;
|
|
|
|
bool hasCollisionXZ = false;
|
|
bool hasCollisionY = false;
|
|
|
|
ret->x += dtime*ent->metad5;
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
ret->x -= dtime*ent->metad5;
|
|
ent->metad5 = 0.0;
|
|
player_hp -= ent->metai1;
|
|
entity2_onHit(ent, ret);
|
|
} else if(is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp2(ret, 10, 17)) {
|
|
ret->x -= dtime*ent->metad5;
|
|
ent->metad5 = 0.0;
|
|
hasCollisionXZ = true;
|
|
}
|
|
|
|
ret->z += dtime*ent->metad7;
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
ret->z -= dtime*ent->metad7;
|
|
ent->metad7 = 0.0;
|
|
player_hp -= ent->metai1;
|
|
entity2_onHit(ent, ret);
|
|
} else if(is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp2(ret, 10, 17)) {
|
|
ret->z -= dtime*ent->metad7;
|
|
ent->metad7 = 0.0;
|
|
hasCollisionXZ = true;
|
|
}
|
|
|
|
ret->y += dtime*ent->metad6;
|
|
if(distance_pt_cube_0_3d_infinite(camx, camy, camz, ret) <= min_dist) {
|
|
ret->y -= dtime*ent->metad6;
|
|
player_hp -= ent->metai1;
|
|
entity2_onHit(ent, ret);
|
|
ent->metad6 = 0.0;
|
|
} else if(is_colliding_with_map(ret) || is_colliding_with_tp(ret) || is_colliding_with_ent_sp2(ret, 10, 17)) {
|
|
ret->y -= dtime*ent->metad6;
|
|
hasCollisionY = hasCollisionY || (ent->metad6 <= 0.0);
|
|
ent->metad6 = 0.0;
|
|
}
|
|
|
|
if(hasCollisionXZ && hasCollisionY) {
|
|
ent->metad6 += sqrt(2.0*gravity_factor*ent->metad2);
|
|
//printf("%lf\n", ent->metad3);
|
|
}
|
|
|
|
if(ret->y <= -48.0) {
|
|
*(ent->hitpoints) = 0;
|
|
}
|
|
} else if((choffxE == 0 && choffzE == 0) || (ent->metai3 != -1 && buttonSwitch[ent->metai3])) {
|
|
ent->metai2 = 1;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------------------------------------------- //
|
|
// ---------------------------------------------------------------------------------------------------------------------------------------------------------- //
|
|
|
|
void movableCrate_onHit(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
//printf("(+%lf, +%lf)\n", camvx, camvz);
|
|
//entToVelCheck = ent;
|
|
//doUpdateEntVel = true;
|
|
updateF_movableCrate(ret, (double)dtime, ent);
|
|
}
|
|
|
|
void lava_onHit(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
player_hp -= ent->metai1;
|
|
}
|
|
|
|
void active_math(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
if(ent->metad1 == 0.0) {
|
|
mathSignal = true;
|
|
ent->metad1 = ent->metad2;
|
|
}
|
|
}
|
|
|
|
void spinning_translate(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
// ret->ye
|
|
}
|
|
|
|
// metai1 = button freq (same for blocks)
|
|
// matei2 = trigger state (0/1) ('OFF state' for blocks)
|
|
// metad1 = button activation time
|
|
void update_button(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
if(!buttonSwitch[ent->metai1]) {
|
|
buttonSwitch[ent->metai1] = true;
|
|
buttonTimes[ent->metai1] = ent->metad1;
|
|
buttonMaxT[ent->metai1] = ent->metad1;
|
|
}
|
|
}
|
|
|
|
void detectHit(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
if(ret->red == 193) {
|
|
ret->red = 0;
|
|
ret->green = 192;
|
|
ret->blue = 0;
|
|
coins += *hp;
|
|
player_hp -= (*dmg);
|
|
if(*dmg != 0) {
|
|
fade_dmg = 255;
|
|
}
|
|
*hp = 0;
|
|
}
|
|
}
|
|
|
|
void money(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
coins += *hp;
|
|
player_hp -= (*dmg);
|
|
if(*dmg != 0) {
|
|
fade_dmg = 255;
|
|
}
|
|
*hp = 0;
|
|
}
|
|
|
|
void translatePlayer(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
bool canMove = (ent->metai5 == -1) || xor(buttonSwitch[ent->metai5], (bool)ent->metai4);
|
|
if(canMove) {
|
|
double dx = ent->metad4*(cos((double)(ent->metai1*(sim_time+(double)dtime)/ent->metai2 + ent->metai3*3.14159/180.0))-cos((double)(ent->metai1*sim_time/ent->metai2 + ent->metai3*3.14159/180.0)));
|
|
double dy = ent->metad5*(cos((double)(ent->metai1*(sim_time+(double)dtime)/ent->metai2 + ent->metai3*3.14159/180.0))-cos((double)(ent->metai1*sim_time/ent->metai2 + ent->metai3*3.14159/180.0)));
|
|
double dz = ent->metad6*(cos((double)(ent->metai1*(sim_time+(double)dtime)/ent->metai2 + ent->metai3*3.14159/180.0))-cos((double)(ent->metai1*sim_time/ent->metai2 + ent->metai3*3.14159/180.0)));
|
|
//fx += dx/(dtime*dtime);
|
|
//fy += dy/(dtime*dtime);
|
|
//fz += dz/(dtime*dtime);
|
|
camvx += dx/(dtime);
|
|
camvy += dy/(dtime);
|
|
camvz += dz/(dtime);
|
|
}
|
|
}
|
|
|
|
void translatePlayerLine(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
bool canMove = (ent->metai5 == -1) || xor(buttonSwitch[ent->metai5], (bool)ent->metai4);
|
|
if(canMove) {
|
|
double dx = (ent->metai1)*ent->metad4*dtime;
|
|
double dy = (ent->metai2)*ent->metad5*dtime;
|
|
double dz = (ent->metai3)*ent->metad6*dtime;
|
|
//fx += dx/(dtime*dtime);
|
|
//fy += dy/(dtime*dtime);
|
|
//fz += dz/(dtime*dtime);
|
|
camvx += dx/(dtime);
|
|
camvy += dy/(dtime);
|
|
}
|
|
}
|
|
|
|
void go_to_player(float dtime, entity* ent, cube_0* ret) {
|
|
double dx = (ret->x+ret->w/2 - (camx-choffxE));
|
|
double dy = (ret->y+ret->h/2 - (camy));
|
|
double dz = (ret->z+ret->d/2 - (camz-choffzE));
|
|
double total = sqrt(dx*dx + dy*dy + dz*dz);
|
|
dx = dx/total;
|
|
dy = dy/total;
|
|
dz = dz/total;
|
|
ret->x -= dtime*dx;
|
|
if(is_colliding_with_map(ret) || is_colliding_with_tp(ret)) {
|
|
ret->x += dtime*dx;
|
|
}
|
|
ret->y -= dtime*dy;
|
|
if(is_colliding_with_map(ret) || is_colliding_with_tp(ret)) {
|
|
ret->y += dtime*dy;
|
|
}
|
|
ret->z -= dtime*dz;
|
|
if(is_colliding_with_map(ret) || is_colliding_with_tp(ret)) {
|
|
ret->z += dtime*dz;
|
|
}
|
|
//if((int)(ret->x+ret->y+ret->z) != (int)(ret->x+ret->y+ret->z-dx-dy-dz)) {
|
|
|
|
//}
|
|
}
|
|
|
|
void explodeOnHit(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
player_hp -= (*dmg);
|
|
if(*dmg != 0) {
|
|
fade_dmg = 255;
|
|
}
|
|
*hp = 0;
|
|
}
|
|
|
|
// metai1 = id of the interface
|
|
// metach1 = text (stored here to free() easily)
|
|
void pop_text(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
interface_set(ent->metai1);
|
|
}
|
|
|
|
// metai1 = id of the interface
|
|
// metai2 = room count
|
|
// metach1 = dest folder
|
|
// metach2 = text (stored here to free() easily)
|
|
void pop_and_tp(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
interface_set(ent->metai1);
|
|
newRoomName = ent->metach1;
|
|
newRoomCount = ent->metai2;
|
|
//printf("%s %d\n", newRoomName, newRoomCount);
|
|
switchRoom = true;
|
|
}
|
|
|
|
// metai1 = id of the interface
|
|
// metai2 = price
|
|
// metai3 = doPay
|
|
// metach1 = text (stored here to free() easily)
|
|
void locker(float dtime, int* hp, int* dmg, entity* ent, cube_0* ret) {
|
|
//printf("%d %d %d <<<<\n", ent->metai1, ent->metai2, ent->metai3);
|
|
//interface_set(ent->metai1);
|
|
if(coins >= ent->metai2) {
|
|
if(ent->metai3) {
|
|
coins -= ent->metai2;
|
|
}
|
|
*hp = 0;
|
|
}
|
|
} |