diff --git a/README.md b/README.md index 90f58990d..43a737aad 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ This means that plugins that do binary code analysis (Orpheu for example) probab | mp_ammo_respawn_time | 20 | 0.0 | - | The respawn time for ammunition. | | mp_vote_flags | km | 0 | - | Vote systems enabled in server.
`0` voting disabled
`k` votekick enabled via `vote` command
`m` votemap enabled via `votemap` command | | mp_votemap_min_time | 180 | 0.0 | - | Minimum seconds that must elapse on map before `votemap` command can be used. | - +| mp_flymove_method | 0 | 0.0 | - | When non-zero, sets alternative and more accuracy flymove method. | ## How to install zBot for CS 1.6? diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp index 789435938..69447c01e 100644 --- a/regamedll/dlls/game.cpp +++ b/regamedll/dlls/game.cpp @@ -188,6 +188,8 @@ cvar_t ammo_respawn_time = { "mp_ammo_respawn_time", "20", FCVAR_SERVER, 2 cvar_t vote_flags = { "mp_vote_flags", "km", 0, 0.0f, nullptr }; cvar_t votemap_min_time = { "mp_votemap_min_time", "180", 0, 180.0f, nullptr }; +cvar_t flymove_method = { "mp_flymove_method", "0", 0, 0.0f, nullptr }; + void GameDLL_Version_f() { if (Q_stricmp(CMD_ARGV(1), "version") != 0) @@ -460,6 +462,8 @@ void EXT_FUNC GameDLLInit() CVAR_REGISTER(&vote_flags); CVAR_REGISTER(&votemap_min_time); + CVAR_REGISTER(&flymove_method); + // print version CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n"); diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h index 09da5305a..139d42fa0 100644 --- a/regamedll/dlls/game.h +++ b/regamedll/dlls/game.h @@ -208,6 +208,7 @@ extern cvar_t weapon_respawn_time; extern cvar_t ammo_respawn_time; extern cvar_t vote_flags; extern cvar_t votemap_min_time; +extern cvar_t flymove_method; #endif @@ -215,4 +216,6 @@ extern cvar_t scoreboard_showmoney; extern cvar_t scoreboard_showhealth; extern cvar_t scoreboard_showdefkit; + + void GameDLLInit(); diff --git a/regamedll/pm_shared/pm_shared.cpp b/regamedll/pm_shared/pm_shared.cpp index fa106c09b..e9d98e647 100644 --- a/regamedll/pm_shared/pm_shared.cpp +++ b/regamedll/pm_shared/pm_shared.cpp @@ -642,9 +642,184 @@ void PM_FixupGravityVelocity() pmove->velocity[2] -= (pmove->movevars->gravity * pmove->frametime * ent_gravity * 0.5); PM_CheckVelocity(); } +#ifdef REGAMEDLL_ADD +int PM_FlyMove_New() +{ + int bumpcount, numbumps; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[MAX_CLIP_PLANES]; + vec3_t primal_velocity; + vec3_t clipVelocity; + int i, j, k; + pmtrace_t trace; + vec3_t end; + float time_left; + float into; + vec3_t endVelocity; + vec3_t endClipVelocity; + int blocked; + + numbumps = 4; + + VectorCopy(pmove->velocity, primal_velocity); + + + time_left = pmove->frametime; + + numplanes = 0; + blocked = 0x00; // Assume not blocked + + // never turn against original velocity + VectorCopy(pmove->velocity, planes[numplanes]); + VectorNormalize(planes[numplanes]); + numplanes++; + + for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { + + // calculate position we are trying to move to + VectorMA(pmove->origin, time_left, pmove->velocity, end); + + // see if we can make it there + trace = pmove->PM_PlayerTrace(pmove->origin, end, PM_NORMAL, -1); + + if (trace.allsolid) { + // entity is completely trapped in another solid + pmove->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration + return 4; + } + + if (trace.fraction > 0) { + // actually covered some distance + VectorCopy(trace.endpos, pmove->origin); + } + if (trace.fraction == 1) { + break; // moved the entire distance + } + + // save entity for contact + PM_AddToTouched(trace, pmove->velocity); + + // If the plane we hit has a high z component in the normal, then + // it's probably a floor + if (trace.plane.normal[2] > 0.7f) + { + // floor + blocked |= 0x01; + } + + // If the plane has a zero z component in the normal, then it's a + // step or wall + if (!trace.plane.normal[2]) + { + // step / wall + blocked |= 0x02; + } + + time_left -= time_left * trace.fraction; + + if (numplanes >= MAX_CLIP_PLANES) { + // this shouldn't really happen + VectorClear(pmove->velocity); + break; + } + + // + // if this is the same plane we hit before, nudge velocity + // out along it, which fixes some epsilon issues with + // non-axial planes + // + for (i = 0; i < numplanes; i++) { + if (DotProduct(trace.plane.normal, planes[i]) > 0.99) { + VectorAdd(trace.plane.normal, pmove->velocity, pmove->velocity); + break; + } + } + if (i < numplanes) { + continue; + } + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; + + // + // modify velocity so it parallels all of the clip planes + // + + // find a plane that it enters + for (i = 0; i < numplanes; i++) { + into = DotProduct(pmove->velocity, planes[i]); + if (into >= 0.1) { + continue; // move doesn't interact with the plane + } + + // slide along the plane + PM_ClipVelocity(pmove->velocity, planes[i], clipVelocity, 1); + + // slide along the plane + PM_ClipVelocity(endVelocity, planes[i], endClipVelocity, 1); + + // see if there is a second plane that the new move enters + for (j = 0; j < numplanes; j++) { + if (j == i) { + continue; + } + if (DotProduct(clipVelocity, planes[j]) >= 0.1) { + continue; // move doesn't interact with the plane + } + + // try clipping the move to the plane + PM_ClipVelocity(clipVelocity, planes[j], clipVelocity, 1); + PM_ClipVelocity(endClipVelocity, planes[j], endClipVelocity, 1); + + // see if it goes back into the first clip plane + if (DotProduct(clipVelocity, planes[i]) >= 0) { + continue; + } + + // slide the original velocity along the crease + CrossProduct(planes[i], planes[j], dir); + VectorNormalize(dir); + d = DotProduct(dir, pmove->velocity); + VectorScale(dir, d, clipVelocity); + + CrossProduct(planes[i], planes[j], dir); + VectorNormalize(dir); + d = DotProduct(dir, endVelocity); + VectorScale(dir, d, endClipVelocity); + + // see if there is a third plane the the new move enters + for (k = 0; k < numplanes; k++) { + if (k == i || k == j) { + continue; + } + if (DotProduct(clipVelocity, planes[k]) >= 0.1) { + continue; // move doesn't interact with the plane + } + + // stop dead at a tripple plane interaction + VectorClear(pmove->velocity); + return 4; + } + } + + // if we have fixed all interactions, try another move + VectorCopy(clipVelocity, pmove->velocity); + VectorCopy(endClipVelocity, endVelocity); + break; + } + } + + return blocked; +} +#endif int PM_FlyMove() { +#ifdef REGAMEDLL_ADD + if (flymove_method.value) + return PM_FlyMove_New(); +#endif int bumpcount, numbumps; vec3_t dir; float d;