BotLib: My last commit before weekend hits. More pathfinding work, added
a temporary interface for in-game waypointing... Bots will combat you too.
This commit is contained in:
parent
c76cdc5903
commit
5edcdb892c
29 changed files with 583 additions and 168 deletions
|
@ -3,6 +3,23 @@ set -e
|
|||
|
||||
FTE_MAKEFILE=./src/engine/engine/Makefile
|
||||
BUILD_SDL2=0
|
||||
BUILD_DEBUG=1
|
||||
|
||||
if [ "$BUILD_DEBUG" -eq 1 ]; then
|
||||
MAKETARGET=m-dbg
|
||||
OUTPUT=./debug
|
||||
else
|
||||
MAKETARGET=m-rel
|
||||
OUTPUT=./release
|
||||
fi
|
||||
|
||||
if [ "$BUILD_SDL2" -eq 1 ]; then
|
||||
PLATFORM=SDL2
|
||||
OUTPUT=$OUTPUT/fteqw64-sdl2
|
||||
else
|
||||
PLATFORM=linux64
|
||||
OUTPUT=$OUTPUT/fteqw64
|
||||
fi
|
||||
|
||||
mkdir -p ./bin
|
||||
|
||||
|
@ -18,15 +35,9 @@ else
|
|||
cd ./engine/engine
|
||||
fi
|
||||
|
||||
if [ "$BUILD_SDL2" -eq 1 ]; then
|
||||
make -j $(nproc) makelibs FTE_TARGET=SDL2
|
||||
make -j $(nproc) m-rel FTE_TARGET=SDL2
|
||||
cp -v ./release/fteqw-sdl2 ../../../bin/fteqw
|
||||
else
|
||||
make -j $(nproc) makelibs
|
||||
make -j $(nproc) m-rel
|
||||
cp -v ./release/fteqw ../../../bin/fteqw
|
||||
fi
|
||||
make -j $(nproc) makelibs FTE_TARGET=$PLATFORM
|
||||
make -j $(nproc) $MAKETARGET FTE_TARGET=$PLATFORM
|
||||
cp -v "$OUTPUT" ../../../bin/fteqw
|
||||
|
||||
make -j $(nproc) sv-rel
|
||||
cp -v ./release/fteqw-sv ../../../bin/fteqw-sv
|
||||
|
|
|
@ -14,6 +14,111 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define BOTROUTE_DESTINATION -1
|
||||
#define BOTROUTE_END -2
|
||||
|
||||
void
|
||||
bot::Pain(void)
|
||||
{
|
||||
player::Pain();
|
||||
|
||||
/* might as well target our attacker */
|
||||
if (!m_eTarget)
|
||||
m_eTarget = g_dmg_eAttacker;
|
||||
}
|
||||
|
||||
void
|
||||
bot::RouteClear(void)
|
||||
{
|
||||
if (!m_iNodes)
|
||||
return;
|
||||
|
||||
m_iCurNode = BOTROUTE_END;
|
||||
m_iNodes = 0;
|
||||
m_flNodeGiveup = 0.0f;
|
||||
memfree(m_pRoute);
|
||||
}
|
||||
|
||||
void
|
||||
bot::WeaponThink(void)
|
||||
{
|
||||
/* clip empty */
|
||||
if (a_ammo1 == 0) {
|
||||
/* still got ammo left */
|
||||
if (a_ammo2 != 0) {
|
||||
input_buttons &= ~INPUT_BUTTON0;
|
||||
input_buttons |= INPUT_BUTTON4;
|
||||
} else {
|
||||
Weapons_SwitchBest(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bot::WeaponAttack(void)
|
||||
{
|
||||
if (m_flAttackTime < time) {
|
||||
if (!m_iAttackMode) {
|
||||
input_buttons |= INPUT_BUTTON0; // Attack
|
||||
}
|
||||
m_flAttackTime = time + 0.1f;
|
||||
}
|
||||
m_iAttackMode = 1 - m_iAttackMode;
|
||||
}
|
||||
|
||||
void
|
||||
bot::BrainThink(int enemyvisible, int enemydistant)
|
||||
{
|
||||
/* we had a target and it's now dead. now what? */
|
||||
if (m_eTarget && m_eTarget.health <= 0) {
|
||||
m_eTarget = __NULL__;
|
||||
RouteClear();
|
||||
} else if (m_eTarget && enemyvisible && enemydistant) {
|
||||
/* we can see the player, but are too far away, plot a route */
|
||||
route_calculate(this, m_eTarget.origin, 0, Bot_RouteCB);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bot::SeeThink(void)
|
||||
{
|
||||
if (m_eTarget)
|
||||
return;
|
||||
|
||||
if (m_flSeeTime > time)
|
||||
return;
|
||||
|
||||
if (autocvar_bot_pacifist)
|
||||
return;
|
||||
|
||||
m_flSeeTime = time + 0.25f;
|
||||
|
||||
for (entity w = world; (w = findfloat(w, ::takedamage, DAMAGE_YES));) {
|
||||
float flDot;
|
||||
|
||||
if (!(w.flags & FL_CLIENT))
|
||||
continue;
|
||||
if (w.health <= 0)
|
||||
continue;
|
||||
|
||||
/* first, is the potential enemy in our field of view? */
|
||||
makevectors(v_angle);
|
||||
vector v = normalize(w.origin - origin);
|
||||
flDot = v * v_forward;
|
||||
|
||||
if (flDot < 90/180)
|
||||
continue;
|
||||
|
||||
other = world;
|
||||
traceline(origin, w.origin, MOVE_OTHERONLY, this);
|
||||
|
||||
if (trace_fraction == 1.0f) {
|
||||
m_eTarget = w;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bot::CheckRoute(void)
|
||||
{
|
||||
|
@ -26,21 +131,29 @@ bot::CheckRoute(void)
|
|||
|
||||
/* level out position/node stuff */
|
||||
if (m_iCurNode < 0) {
|
||||
evenpos = m_vecLastNode;
|
||||
evenpos[2] = origin[2];
|
||||
evenpos = m_vecLastNode - origin;
|
||||
} else {
|
||||
evenpos = m_pRoute[m_iCurNode].m_vecDest;
|
||||
evenpos[2] = origin[2];
|
||||
evenpos = m_pRoute[m_iCurNode].m_vecDest - origin;
|
||||
}
|
||||
evenpos[2] *= 0.25f;
|
||||
|
||||
flDist = floor(vlen(evenpos - origin));
|
||||
flDist = floor(vlen(evenpos));
|
||||
|
||||
if ( flDist < 16 ) {
|
||||
if (flDist < 16) {
|
||||
dprint(sprintf("^2CBaseMonster::^3CheckRoute^7: " \
|
||||
"%s reached node\n", this.targetname));
|
||||
m_iCurNode--;
|
||||
velocity = [0,0,0]; /* clamp friction */
|
||||
velocity *= 0.5f;
|
||||
|
||||
if (m_iCurNode >= 0) {
|
||||
print(sprintf("NODE FLAGS: %i\n", m_pRoute[m_iCurNode].m_iFlags));
|
||||
|
||||
/* if a node is flagged as jumpy, jump! */
|
||||
if (m_pRoute[m_iCurNode].m_iFlags & WP_JUMP)
|
||||
input_buttons |= INPUT_BUTTON2;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* we've still traveling and from this node we may be able to walk
|
||||
* directly to our end-destination */
|
||||
if (m_iCurNode > -1) {
|
||||
|
@ -53,43 +166,36 @@ bot::CheckRoute(void)
|
|||
m_iCurNode = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
traceline( origin + view_ofs, m_pRoute[m_iCurNode].m_vecDest, MOVE_NORMAL, this );
|
||||
traceline(origin + view_ofs, m_pRoute[m_iCurNode].m_vecDest, MOVE_NORMAL, this);
|
||||
|
||||
/* we can't trace against our next waypoint... that should never happen */
|
||||
if ( trace_fraction != 1.0f ) {
|
||||
if (trace_fraction != 1.0f) {
|
||||
m_flNodeGiveup += frametime;
|
||||
} else {
|
||||
/* if we're literally stuck in a corner aiming at something we should
|
||||
* not, also give up */
|
||||
if ( flDist == m_flLastDist ) {
|
||||
if (flDist == m_flLastDist) {
|
||||
m_flNodeGiveup += frametime;
|
||||
} else {
|
||||
m_flNodeGiveup = bound( 0, m_flNodeGiveup - frametime, 1.0 );
|
||||
m_flNodeGiveup = bound(0, m_flNodeGiveup - frametime, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_flLastDist = flDist;
|
||||
|
||||
if ( m_flNodeGiveup >= 1.0f ) {
|
||||
dprint(sprintf("bot::CheckRoute: %s gave up route\n",
|
||||
this.netname));
|
||||
|
||||
m_iCurNode = -2;
|
||||
m_flNodeGiveup = 0.0f;
|
||||
} else if ( m_flNodeGiveup >= 0.5f ) {
|
||||
/* after one second, also give up the route */
|
||||
if (m_flNodeGiveup >= 1.0f || m_iCurNode <= BOTROUTE_END) {
|
||||
RouteClear();
|
||||
} else if (m_flNodeGiveup >= 0.5f) {
|
||||
/* attempt a jump after half a second */
|
||||
input_buttons |= INPUT_BUTTON2;
|
||||
}
|
||||
|
||||
if (m_iCurNode < -1) {
|
||||
dprint(sprintf("bot::CheckRoute: %s calculates new route\n",
|
||||
this.netname));
|
||||
|
||||
m_iNodes = 0;
|
||||
memfree( m_pRoute );
|
||||
route_calculate( this, Route_SelectDestination( this ), 0, Bot_RouteCB );
|
||||
return;
|
||||
} else {
|
||||
/* entire way-link needs to be crouched. that's the law of the land */
|
||||
if (m_pRoute[m_iCurNode].m_iFlags & WP_CROUCH)
|
||||
input_buttons |= INPUT_BUTTON8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +213,10 @@ bot::RunAI(void)
|
|||
|
||||
/* attempt to respawn when dead */
|
||||
if (health <= 0) {
|
||||
input_buttons |= INPUT_BUTTON0;
|
||||
RouteClear();
|
||||
WeaponAttack();
|
||||
m_eTarget = __NULL__;
|
||||
return;
|
||||
}
|
||||
|
||||
/* create our first route */
|
||||
|
@ -123,8 +232,8 @@ bot::RunAI(void)
|
|||
}
|
||||
}
|
||||
|
||||
//WeaponThink();
|
||||
//PickEnemy();
|
||||
WeaponThink();
|
||||
SeeThink();
|
||||
|
||||
enemyvisible = FALSE;
|
||||
enemydistant = FALSE;
|
||||
|
@ -138,69 +247,108 @@ bot::RunAI(void)
|
|||
}
|
||||
|
||||
if (enemyvisible) {
|
||||
//WeaponAttack();
|
||||
WeaponAttack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BrainThink(enemyvisible, enemydistant);
|
||||
CheckRoute();
|
||||
|
||||
if (m_iNodes) {
|
||||
vector vecNewAngles;
|
||||
vector vecDirection;
|
||||
|
||||
if (!m_eTarget || !enemyvisible) {
|
||||
/* aim at the next node */
|
||||
if (m_iCurNode == -1)
|
||||
if (m_iCurNode == BOTROUTE_DESTINATION)
|
||||
aimpos = m_vecLastNode;
|
||||
else
|
||||
aimpos = m_pRoute[m_iCurNode].m_vecDest;
|
||||
else {
|
||||
if (m_iCurNode > 0)
|
||||
aimpos = m_pRoute[m_iCurNode - 1].m_vecDest;
|
||||
else
|
||||
aimpos = m_pRoute[m_iCurNode].m_vecDest;
|
||||
}
|
||||
} else {
|
||||
/* aim towards the enemy */
|
||||
aimpos = m_eTarget.origin;
|
||||
}
|
||||
|
||||
/* lerping speed */
|
||||
flLerp = bound(0.0f, 1.0f - (frametime * 15), 1.0f);
|
||||
/* lerping speed, faster when we've got a target */
|
||||
if (m_eTarget && enemyvisible)
|
||||
flLerp = bound(0.0f, frametime * 45, 1.0f);
|
||||
else
|
||||
flLerp = bound(0.0f, frametime * 30, 1.0f);
|
||||
|
||||
/* that's the old angle */
|
||||
makevectors(v_angle);
|
||||
vector vNewAngles = v_forward;
|
||||
vecNewAngles = v_forward;
|
||||
|
||||
/* aimdir = final angle */
|
||||
/* aimdir = new final angle */
|
||||
aimdir = vectoangles(aimpos - origin);
|
||||
makevectors(aimdir);
|
||||
|
||||
/* slowly lerp towards the final angle */
|
||||
vNewAngles[0] = Math_Lerp(vNewAngles[0], v_forward[0], flLerp);
|
||||
vNewAngles[1] = Math_Lerp(vNewAngles[1], v_forward[1], flLerp);
|
||||
vNewAngles[2] = Math_Lerp(vNewAngles[2], v_forward[2], flLerp);
|
||||
vecNewAngles[0] = Math_Lerp(vecNewAngles[0], v_forward[0], flLerp);
|
||||
vecNewAngles[1] = Math_Lerp(vecNewAngles[1], v_forward[1], flLerp);
|
||||
vecNewAngles[2] = Math_Lerp(vecNewAngles[2], v_forward[2], flLerp);
|
||||
|
||||
/* make sure we're aiming tight */
|
||||
v_angle = vectoangles(vNewAngles);
|
||||
v_angle = vectoangles(vecNewAngles);
|
||||
v_angle[0] = Math_FixDelta(v_angle[0]);
|
||||
v_angle[1] = Math_FixDelta(v_angle[1]);
|
||||
v_angle[2] = Math_FixDelta(v_angle[2]);
|
||||
input_angles = v_angle;
|
||||
angles[0] = Math_FixDelta(v_angle[0]);
|
||||
angles[1] = Math_FixDelta(v_angle[1]);
|
||||
angles[2] = Math_FixDelta(v_angle[2]);
|
||||
input_angles = v_angle;
|
||||
|
||||
/* now that aiming is sorted, we need to correct the movement */
|
||||
if ((m_eTarget && enemyvisible && !enemydistant) && vlen(aimpos - origin) > 256) {
|
||||
/* we are far away, inch closer */
|
||||
aimpos = m_eTarget.origin;
|
||||
} else {
|
||||
if (m_iCurNode == BOTROUTE_DESTINATION)
|
||||
aimpos = m_vecLastNode;
|
||||
else
|
||||
aimpos = m_pRoute[m_iCurNode].m_vecDest;
|
||||
}
|
||||
|
||||
|
||||
/* now we'll set the movevalues relative to the input_angle */
|
||||
vector direction = normalize(aimpos - origin) * 240;
|
||||
vecDirection = normalize(aimpos - origin) * 240;
|
||||
makevectors(input_angles);
|
||||
input_movevalues = [v_forward * direction, v_right * direction, v_up * direction];
|
||||
input_movevalues = [v_forward * vecDirection, v_right * vecDirection, v_up * vecDirection];
|
||||
}
|
||||
|
||||
/* press any buttons needed */
|
||||
button0 = input_buttons & INPUT_BUTTON0; //attack
|
||||
button2 = input_buttons & INPUT_BUTTON2; //jump
|
||||
button3 = input_buttons & INPUT_BUTTON3; //tertiary
|
||||
button4 = input_buttons & INPUT_BUTTON4; //reload
|
||||
button5 = input_buttons & INPUT_BUTTON5; //secondary
|
||||
button6 = input_buttons & INPUT_BUTTON6; //use
|
||||
button7 = input_buttons & INPUT_BUTTON7; //unused
|
||||
button8 = input_buttons & INPUT_BUTTON8; //duck
|
||||
button0 = input_buttons & INPUT_BUTTON0; // attack
|
||||
button2 = input_buttons & INPUT_BUTTON2; // jump
|
||||
button3 = input_buttons & INPUT_BUTTON3; // tertiary
|
||||
button4 = input_buttons & INPUT_BUTTON4; // reload
|
||||
button5 = input_buttons & INPUT_BUTTON5; // secondary
|
||||
button6 = input_buttons & INPUT_BUTTON6; // use
|
||||
button7 = input_buttons & INPUT_BUTTON7; // unused
|
||||
button8 = input_buttons & INPUT_BUTTON8; // duck
|
||||
movement = input_movevalues;
|
||||
}
|
||||
|
||||
void
|
||||
bot::PreFrame(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bot::PostFrame(void)
|
||||
{
|
||||
/* we've picked something new up */
|
||||
if (m_iOldItems != g_items) {
|
||||
//Weapons_SwitchBest(this);
|
||||
m_iOldItems = g_items;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bot::bot(void)
|
||||
{
|
||||
classname = "player";
|
||||
}
|
||||
|
|
|
@ -36,11 +36,27 @@ class bot:player
|
|||
|
||||
/* combat */
|
||||
entity m_eTarget;
|
||||
int m_iAttackMode;
|
||||
float m_flAttackTime;
|
||||
|
||||
/* items */
|
||||
int m_iOldItems;
|
||||
|
||||
/* visual */
|
||||
float m_flSeeTime;
|
||||
|
||||
void(void) bot;
|
||||
|
||||
virtual void(void) Pain;
|
||||
virtual void(void) RouteClear;
|
||||
virtual void(void) WeaponThink;
|
||||
virtual void(void) WeaponAttack;
|
||||
virtual void(void) SeeThink;
|
||||
virtual void(int, int) BrainThink;
|
||||
virtual void(void) RunAI;
|
||||
virtual void(void) CheckRoute;
|
||||
virtual void(void) PreFrame;
|
||||
virtual void(void) PostFrame;
|
||||
};
|
||||
|
||||
entity Bot_AddQuick(void);
|
||||
|
|
|
@ -39,7 +39,6 @@ Bot_AddQuick(void)
|
|||
entity oself;
|
||||
|
||||
oself = self;
|
||||
self = world;
|
||||
self = spawnclient();
|
||||
|
||||
if (!self) {
|
||||
|
|
17
src/botlib/cvar.h
Normal file
17
src/botlib/cvar.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
var int autocvar_bot_pacifist = FALSE;
|
|
@ -17,3 +17,5 @@
|
|||
#include "bot.h"
|
||||
#include "botinfo.h"
|
||||
#include "route.h"
|
||||
#include "cvar.h"
|
||||
#include "way.h"
|
||||
|
|
|
@ -86,7 +86,7 @@ vector Route_SelectDestination( bot target )
|
|||
int range;
|
||||
for ( temp = world; ( temp = findfloat( temp, ::botinfo, BOTINFO_HEALTH ) ); ) {
|
||||
range = vlen( temp.origin - target.origin );
|
||||
if ( ( range < bestrange ) && ( temp.solid = SOLID_TRIGGER ) ) {
|
||||
if ( ( range < bestrange ) && ( temp.solid == SOLID_TRIGGER ) ) {
|
||||
bestrange = range;
|
||||
dest = temp;
|
||||
}
|
||||
|
|
118
src/botlib/way.c
118
src/botlib/way.c
|
@ -14,16 +14,6 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define COST_INFINITE 99999
|
||||
|
||||
enumflags
|
||||
{
|
||||
WP_JUMP, /* also implies that the bot must first go behind the wp... */
|
||||
WP_CLIMB,
|
||||
WP_CROUCH,
|
||||
WP_USE
|
||||
};
|
||||
|
||||
typedef struct waypoint_s
|
||||
{
|
||||
vector vecOrigin;
|
||||
|
@ -166,11 +156,18 @@ Way_Waypoint_Create(entity ePlayer, int iAutoLink)
|
|||
n->neighbour = __NULL__;
|
||||
n->iNeighbours = 0;
|
||||
|
||||
if (iAutoLink) {
|
||||
if (iAutoLink == 1) {
|
||||
Way_AutoLink(n);
|
||||
} else {
|
||||
if (iID != 0) {
|
||||
Way_LinkWaypoints(n, &g_pWaypoints[iID-1]);
|
||||
if (iAutoLink == 0) {
|
||||
Way_LinkWaypoints(n, &g_pWaypoints[iID-1]);
|
||||
Way_LinkWaypoints(&g_pWaypoints[iID-1], n);
|
||||
} else if (iAutoLink -1) {
|
||||
Way_LinkWaypoints(&g_pWaypoints[iID-1], n);
|
||||
} else {
|
||||
Way_LinkWaypoints(n, &g_pWaypoints[iID-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,6 +267,26 @@ Way_FindClosestWaypoint(vector vecOrigin)
|
|||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
Way_GoToPoint(entity pl)
|
||||
{
|
||||
vector vecSrc;
|
||||
makevectors(pl.v_angle);
|
||||
vecSrc = pl.origin + pl.view_ofs;
|
||||
traceline(vecSrc, vecSrc + (v_forward * 4096), FALSE, pl);
|
||||
print(sprintf("Telling all bots to go to %v\n", trace_endpos));
|
||||
|
||||
for (entity a = world; ( a = find( a, classname, "player" ) ); ) {
|
||||
if ( clienttype(a) != CLIENTTYPE_REAL ) {
|
||||
bot targ;
|
||||
targ = (bot)a;
|
||||
targ.RouteClear();
|
||||
route_calculate(targ, pl.origin, 0, Bot_RouteCB);
|
||||
print(sprintf("Told bot to go to %v\n", trace_endpos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Way_DrawDebugInfo(void)
|
||||
{
|
||||
|
@ -317,6 +334,7 @@ Way_DrawDebugInfo(void)
|
|||
|
||||
for (int j = 0i; j < w->iNeighbours; j++) {
|
||||
int k = w->neighbour[j].node;
|
||||
int fl = w->neighbour[j].iFlags;
|
||||
|
||||
if (k < 0i || k >= g_iWaypoints) {
|
||||
break;
|
||||
|
@ -324,9 +342,81 @@ Way_DrawDebugInfo(void)
|
|||
|
||||
waypoint_t *w2 = &g_pWaypoints[k];
|
||||
|
||||
R_PolygonVertex(org, '0 1', '1 0 1', 1);
|
||||
R_PolygonVertex(w2->vecOrigin, '1 1', [0,1,0], 1);
|
||||
if (fl & WP_JUMP) {
|
||||
R_PolygonVertex(org, [0,1], [1,0,0], 1);
|
||||
R_PolygonVertex(w2->vecOrigin, [1,1], [0,1,0], 1);
|
||||
} else {
|
||||
R_PolygonVertex(org, [0,1], [1,0,1], 1);
|
||||
R_PolygonVertex(w2->vecOrigin, [1,1], [0,1,0], 1);
|
||||
}
|
||||
R_EndPolygon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Way_Cmd(void)
|
||||
{
|
||||
switch (argv(1)) {
|
||||
case "goto":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_GoToPoint( self );
|
||||
break;
|
||||
case "add":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_Create( self, 1 );
|
||||
break;
|
||||
case "addchain":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_Create( self, 0 );
|
||||
break;
|
||||
case "addltn":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_Create( self, -1 );
|
||||
break;
|
||||
case "addntl":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_Create( self, -2 );
|
||||
break;
|
||||
case "addspawns":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_CreateSpawns();
|
||||
break;
|
||||
case "delete":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_Delete( Way_FindClosestWaypoint( self.origin ) );
|
||||
break;
|
||||
case "radius":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_SetRadius( Way_FindClosestWaypoint( self.origin ), stof( argv( 2 ) ) );
|
||||
break;
|
||||
case "makejump":
|
||||
if ( !self ) {
|
||||
return;
|
||||
}
|
||||
Way_Waypoint_MakeJump( Way_FindClosestWaypoint( self.origin ) );
|
||||
break;
|
||||
case "save":
|
||||
Way_DumpWaypoints( argv( 2 ) );
|
||||
break;
|
||||
case "load":
|
||||
Way_ReadWaypoints( argv( 2 ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
25
src/botlib/way.h
Normal file
25
src/botlib/way.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define COST_INFINITE 99999
|
||||
|
||||
enumflags
|
||||
{
|
||||
WP_JUMP, /* also implies that the bot must first go behind the wp... */
|
||||
WP_CLIMB,
|
||||
WP_CROUCH,
|
||||
WP_USE
|
||||
};
|
|
@ -61,6 +61,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
|
|||
registercommand("_fnchat_msg");
|
||||
registercommand("dev_sunpos");
|
||||
registercommand("dev_measure");
|
||||
registercommand("way_menu");
|
||||
|
||||
precache_model("sprites/640_pain.spr");
|
||||
precache_model("sprites/crosshairs.spr");
|
||||
|
@ -87,6 +88,71 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
|
|||
Titles_Init();
|
||||
Sentences_Init();
|
||||
Decals_Init();
|
||||
|
||||
/* waypoint menu */
|
||||
{
|
||||
titles_t way_text;
|
||||
way_text.m_strName = "WAY_MENU";
|
||||
way_text.m_strMessage = "1.\tAdd Waypoint\n" \
|
||||
"2.\tAdd Chain Waypoint\n" \
|
||||
"3.\tAdd Spawnpoint Waypoints\n" \
|
||||
"4.\tDelete Closest Waypoint\n" \
|
||||
"5.\tMake Closest Jumpy\n" \
|
||||
"6.\tAdd One-Way New-To-Last\n" \
|
||||
"7.\tAdd One-Way Last-To-New\n" \
|
||||
"8.\tSave File\n" \
|
||||
"9.\tLoad File\n" \
|
||||
"0.\tExit\n";
|
||||
way_text.m_flPosX = 0;
|
||||
way_text.m_flPosY = -1;
|
||||
way_text.m_iEffect = 0;
|
||||
way_text.m_vecColor1 = [1,1,1];
|
||||
way_text.m_vecColor2 = [1,1,1];
|
||||
way_text.m_flFadeIn = 1.0f;
|
||||
way_text.m_flFadeOut = 1.0f;
|
||||
way_text.m_flHoldTime = 1.0f;
|
||||
way_text.m_flFXTime = 1.0f;
|
||||
Titles_AddEntry(way_text);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WAY_MENU(int n)
|
||||
{
|
||||
switch (n) {
|
||||
case 1:
|
||||
localcmd("sv way add\n");
|
||||
break;
|
||||
case 2:
|
||||
localcmd("sv way addchain\n");
|
||||
break;
|
||||
case 3:
|
||||
localcmd("sv way addspawns\n");
|
||||
break;
|
||||
case 4:
|
||||
localcmd("sv way delete\n");
|
||||
break;
|
||||
case 5:
|
||||
localcmd("sv way makejump\n");
|
||||
break;
|
||||
case 6:
|
||||
localcmd("sv way addntl\n");
|
||||
break;
|
||||
case 7:
|
||||
localcmd("sv way addltn\n");
|
||||
break;
|
||||
case 8:
|
||||
localcmd(sprintf("sv way save %s.way\n", mapname));
|
||||
Textmenu_Call("");
|
||||
break;
|
||||
case 9:
|
||||
localcmd(sprintf("sv way load %s.way\n", mapname));
|
||||
Textmenu_Call("");
|
||||
break;
|
||||
case 0:
|
||||
Textmenu_Call("");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rendering Caches */
|
||||
|
@ -725,6 +791,9 @@ CSQC_ConsoleCommand(string sCMD)
|
|||
case "slot10":
|
||||
HUD_SlotSelect(9);
|
||||
break;
|
||||
case "way_menu":
|
||||
Textmenu_Call("WAY_MENU");
|
||||
break;
|
||||
case "_fnchat_msg":
|
||||
CSQC_Parse_Print(argv(1), PRINT_CHAT);
|
||||
break;
|
||||
|
|
|
@ -220,3 +220,26 @@ Titles_Init(void)
|
|||
}
|
||||
fclose(fs_titles);
|
||||
}
|
||||
|
||||
|
||||
titles_t *g_titles;
|
||||
int g_titles_count;
|
||||
|
||||
void
|
||||
Titles_AddEntry(titles_t new)
|
||||
{
|
||||
int newcount = g_titles_count + 1;
|
||||
g_titles = memrealloc(g_titles, sizeof(titles_t), g_titles_count, newcount);
|
||||
g_titles[g_titles_count].m_strName = new.m_strName;
|
||||
g_titles[g_titles_count].m_strMessage = new.m_strMessage;
|
||||
g_titles[g_titles_count].m_flPosX = new.m_flPosX;
|
||||
g_titles[g_titles_count].m_flPosY = new.m_flPosY;
|
||||
g_titles[g_titles_count].m_iEffect = new.m_iEffect;
|
||||
g_titles[g_titles_count].m_vecColor1 = new.m_vecColor1;
|
||||
g_titles[g_titles_count].m_vecColor2 = new.m_vecColor2;
|
||||
g_titles[g_titles_count].m_flFadeIn = new.m_flFadeIn;
|
||||
g_titles[g_titles_count].m_flFadeOut = new.m_flFadeOut;
|
||||
g_titles[g_titles_count].m_flHoldTime = new.m_flHoldTime;
|
||||
g_titles[g_titles_count].m_flFXTime = new.m_flFXTime;
|
||||
g_titles_count++;
|
||||
}
|
||||
|
|
|
@ -403,6 +403,7 @@ HUD_Draw(void)
|
|||
Weapons_DrawCrosshair();
|
||||
HUD_DrawWeaponSelect();
|
||||
Obituary_Draw();
|
||||
Textmenu_Draw();
|
||||
|
||||
if (!(pl.g_items & ITEM_SUIT)) {
|
||||
return;
|
||||
|
@ -420,4 +421,5 @@ void
|
|||
HUD_DrawSpectator(void)
|
||||
{
|
||||
// FIXME
|
||||
Textmenu_Draw();
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ class ambient_generic:CBaseTrigger
|
|||
float
|
||||
ambient_generic::SendEntity(entity ePEnt, float fChanged)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* only override when we're doing the toggle guff */
|
||||
if (m_iLoop == FALSE) {
|
||||
return FALSE;
|
||||
|
|
|
@ -123,6 +123,10 @@ env_laser::Respawn(void)
|
|||
float
|
||||
env_laser::SendEntity(entity ePEnt, float fChanged)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_ENVLASER);
|
||||
WriteFloat(MSG_ENTITY, fChanged);
|
||||
|
||||
|
|
|
@ -53,8 +53,11 @@ class env_sprite:CBaseTrigger
|
|||
};
|
||||
|
||||
float
|
||||
env_sprite::SendEntity(entity pvsent, float flags)
|
||||
env_sprite::SendEntity(entity ePEnt, float flags)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
if (spawnflags & ENVS_PLAYONCE)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -608,9 +608,11 @@ CBaseEntity::SetRenderColor(vector newColor)
|
|||
float
|
||||
CBaseEntity::SendEntity(entity ePEnt, float fChanged)
|
||||
{
|
||||
if (!modelindex) {
|
||||
if (!modelindex)
|
||||
return FALSE;
|
||||
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_ENTITY);
|
||||
WriteFloat(MSG_ENTITY, fChanged);
|
||||
|
|
|
@ -33,8 +33,12 @@ const string g_decal_shader = \
|
|||
|
||||
#ifdef SERVER
|
||||
float
|
||||
decal::SendEntity(entity pvsent, float changedflags)
|
||||
decal::SendEntity(entity ePEnt, float changedflags)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_DECAL);
|
||||
WriteCoord(MSG_ENTITY, origin[0]);
|
||||
WriteCoord(MSG_ENTITY, origin[1]);
|
||||
|
|
|
@ -194,8 +194,11 @@ env_projectedtexture::Trigger(entity act, int state)
|
|||
}
|
||||
|
||||
float
|
||||
env_projectedtexture::SendEntity(entity ePVSEnt, float flFlags)
|
||||
env_projectedtexture::SendEntity(entity ePEnt, float flFlags)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_PROJECTEDTEXTURE);
|
||||
WriteFloat(MSG_ENTITY, flFlags);
|
||||
|
||||
|
|
|
@ -169,8 +169,11 @@ func_monitor::ReceiveEntity(float flFlags)
|
|||
}
|
||||
#else
|
||||
float
|
||||
func_monitor::SendEntity(entity ePVSEnt, float flFlags)
|
||||
func_monitor::SendEntity(entity ePEnt, float flFlags)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_MONITOR);
|
||||
WriteFloat(MSG_ENTITY, flFlags);
|
||||
|
||||
|
|
|
@ -124,8 +124,11 @@ info_particle_system::ReceiveEntity(float flFlags)
|
|||
}
|
||||
#else
|
||||
float
|
||||
info_particle_system::SendEntity(entity ePVSEnt, float flFlags)
|
||||
info_particle_system::SendEntity(entity ePEnt, float flFlags)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_PARTSYSTEM);
|
||||
WriteFloat(MSG_ENTITY, flFlags);
|
||||
|
||||
|
|
|
@ -196,8 +196,11 @@ light_dynamic::Trigger(entity act, int state)
|
|||
}
|
||||
|
||||
float
|
||||
light_dynamic::SendEntity(entity ePVSEnt, float flFlags)
|
||||
light_dynamic::SendEntity(entity ePEnt, float flFlags)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_DLIGHT);
|
||||
WriteFloat(MSG_ENTITY, flFlags);
|
||||
|
||||
|
|
|
@ -26,8 +26,11 @@ Spray_RemoveAll(entity entOwner)
|
|||
}
|
||||
|
||||
float
|
||||
Spray_SendEntity(entity ePVSEnt, float fChanged)
|
||||
Spray_SendEntity(entity ePEnt, float fChanged)
|
||||
{
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_SPRAY);
|
||||
WriteCoord(MSG_ENTITY, self.origin[0]);
|
||||
WriteCoord(MSG_ENTITY, self.origin[1]);
|
||||
|
|
|
@ -91,9 +91,12 @@ trigger_camera::ReceiveEntity(float flFlags)
|
|||
}
|
||||
#else
|
||||
float
|
||||
trigger_camera::SendEntity(entity ePVSEnt, float flFlags)
|
||||
trigger_camera::SendEntity(entity ePEnt, float flFlags)
|
||||
{
|
||||
if (ePVSEnt != m_eLooker)
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||
return FALSE;
|
||||
|
||||
if (ePEnt != m_eLooker)
|
||||
return FALSE;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_OLDCAMERA);
|
||||
|
|
|
@ -49,8 +49,9 @@ MultiplayerRules::PlayerDeath(base_player pl)
|
|||
IntermissionStart();
|
||||
}
|
||||
|
||||
pl.movetype = MOVETYPE_NONE;
|
||||
pl.solid = SOLID_NOT;
|
||||
pl.SetMovetype(MOVETYPE_NONE);
|
||||
pl.SetSolid(SOLID_NOT);
|
||||
pl.SetModelindex(0);
|
||||
pl.takedamage = DAMAGE_NO;
|
||||
pl.gflags &= ~GF_FLASHLIGHT;
|
||||
pl.armor = pl.activeweapon = pl.g_items = 0;
|
||||
|
|
|
@ -97,11 +97,22 @@ void PutClientInServer(void)
|
|||
|
||||
void PlayerPreThink(void)
|
||||
{
|
||||
#ifdef BOT_INCLUDED
|
||||
if (clienttype(self) == CLIENTTYPE_BOT) {
|
||||
((bot)self).PreFrame();
|
||||
}
|
||||
#endif
|
||||
g_grMode.PlayerPreFrame((base_player)self);
|
||||
}
|
||||
|
||||
void PlayerPostThink(void)
|
||||
{
|
||||
#ifdef BOT_INCLUDED
|
||||
if (clienttype(self) == CLIENTTYPE_BOT) {
|
||||
((bot)self).PostFrame();
|
||||
}
|
||||
#endif
|
||||
|
||||
g_grMode.PlayerPostFrame((base_player)self);
|
||||
}
|
||||
|
||||
|
@ -299,47 +310,8 @@ float ConsoleCmd(string cmd)
|
|||
}
|
||||
break;
|
||||
#ifdef BOT_INCLUDED
|
||||
case "way_add":
|
||||
if ( !self ) {
|
||||
return TRUE;
|
||||
}
|
||||
Way_Waypoint_Create( self, TRUE );
|
||||
break;
|
||||
case "way_addchain":
|
||||
if ( !self ) {
|
||||
return TRUE;
|
||||
}
|
||||
Way_Waypoint_Create( self, FALSE );
|
||||
break;
|
||||
case "way_addspawns":
|
||||
if ( !self ) {
|
||||
return TRUE;
|
||||
}
|
||||
Way_Waypoint_CreateSpawns();
|
||||
break;
|
||||
case "way_delete":
|
||||
if ( !self ) {
|
||||
return TRUE;
|
||||
}
|
||||
Way_Waypoint_Delete( Way_FindClosestWaypoint( self.origin ) );
|
||||
break;
|
||||
case "way_radius":
|
||||
if ( !self ) {
|
||||
return TRUE;
|
||||
}
|
||||
Way_Waypoint_SetRadius( Way_FindClosestWaypoint( self.origin ), stof( argv( 1 ) ) );
|
||||
break;
|
||||
case "way_makejump":
|
||||
if ( !self ) {
|
||||
return TRUE;
|
||||
}
|
||||
Way_Waypoint_MakeJump( Way_FindClosestWaypoint( self.origin ) );
|
||||
break;
|
||||
case "way_save":
|
||||
Way_DumpWaypoints( argv( 1 ) );
|
||||
break;
|
||||
case "way_load":
|
||||
Way_ReadWaypoints( argv( 1 ) );
|
||||
case "way":
|
||||
Way_Cmd();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
|
|
@ -63,35 +63,36 @@ HLMultiplayerRules::PlayerDeath(base_player pl)
|
|||
}
|
||||
|
||||
weaponbox_spawn((player)pl);
|
||||
pl.movetype = MOVETYPE_NONE;
|
||||
pl.solid = SOLID_NOT;
|
||||
|
||||
/* either gib, or make a corpse */
|
||||
if (pl.health < -50) {
|
||||
FX_GibHuman(pl.origin);
|
||||
} else {
|
||||
/* Let's handle corpses on the clientside */
|
||||
entity corpse = spawn();
|
||||
setorigin(corpse, pl.origin + [0,0,32]);
|
||||
setmodel(corpse, pl.model);
|
||||
setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
corpse.movetype = MOVETYPE_TOSS;
|
||||
corpse.solid = SOLID_TRIGGER;
|
||||
corpse.modelindex = pl.modelindex;
|
||||
corpse.frame = ANIM_DIESIMPLE;
|
||||
corpse.angles = pl.angles;
|
||||
corpse.velocity = pl.velocity;
|
||||
}
|
||||
|
||||
/* now let's make the real client invisible */
|
||||
pl.SetModelindex(0);
|
||||
pl.SetMovetype(MOVETYPE_NONE);
|
||||
pl.SetSolid(SOLID_NOT);
|
||||
pl.takedamage = DAMAGE_NO;
|
||||
pl.gflags &= ~GF_FLASHLIGHT;
|
||||
pl.armor = pl.activeweapon = pl.g_items = 0;
|
||||
|
||||
pl.think = PutClientInServer;
|
||||
pl.nextthink = time + 4.0f;
|
||||
Sound_Play(pl, CHAN_AUTO, "player.die");
|
||||
|
||||
if (pl.health < -50) {
|
||||
pl.health = 0;
|
||||
FX_GibHuman(pl.origin);
|
||||
return;
|
||||
}
|
||||
|
||||
pl.health = 0;
|
||||
|
||||
/* Let's handle corpses on the clientside */
|
||||
entity corpse = spawn();
|
||||
setorigin(corpse, pl.origin + [0,0,32]);
|
||||
setmodel(corpse, pl.model);
|
||||
setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
corpse.movetype = MOVETYPE_TOSS;
|
||||
corpse.solid = SOLID_TRIGGER;
|
||||
corpse.modelindex = pl.modelindex;
|
||||
corpse.frame = ANIM_DIESIMPLE;
|
||||
corpse.angles = pl.angles;
|
||||
corpse.velocity = pl.velocity;
|
||||
/* force respawn */
|
||||
pl.think = PutClientInServer;
|
||||
pl.nextthink = time + 4.0f;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -89,6 +89,10 @@ float Player_SendEntity(entity ePEnt, float fChanged)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_PLAYER);
|
||||
WriteFloat(MSG_ENTITY, fChanged);
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ PMove_Categorize(void)
|
|||
self.view_ofs = VEC_PLAYER_VIEWPOS;
|
||||
}
|
||||
|
||||
tracebox(self.origin, self.mins, self.maxs, self.origin - [0,0,0.25], FALSE, self);
|
||||
tracebox(self.origin, self.mins, self.maxs, self.origin - [0,0,0.25], MOVE_NORMAL, self);
|
||||
|
||||
if (!trace_startsolid) {
|
||||
if ((trace_fraction < 1) && (trace_plane_normal[2] > 0.7)) {
|
||||
|
@ -149,7 +149,7 @@ PMove_Categorize(void)
|
|||
/* ladder content testing */
|
||||
int oldhitcontents = self.hitcontentsmaski;
|
||||
self.hitcontentsmaski = CONTENTBIT_FTELADDER;
|
||||
tracebox(self.origin, self.mins, self.maxs, self.origin, FALSE, self);
|
||||
tracebox(self.origin, self.mins, self.maxs, self.origin, MOVE_NORMAL, self);
|
||||
self.hitcontentsmaski = oldhitcontents;
|
||||
|
||||
if (trace_endcontentsi & CONTENTBIT_FTELADDER) {
|
||||
|
@ -232,7 +232,7 @@ QPMove_IsStuck(entity eTarget, vector vOffset, vector vecMins, vector vecMaxs)
|
|||
}
|
||||
|
||||
bound = eTarget.origin + vOffset;
|
||||
tracebox(bound, vecMins, vecMaxs, bound, FALSE, eTarget);
|
||||
tracebox(bound, vecMins, vecMaxs, bound, MOVE_NORMAL, eTarget);
|
||||
return trace_startsolid;
|
||||
}
|
||||
|
||||
|
@ -546,7 +546,7 @@ PMove_Fix_Origin(void)
|
|||
for (y = 0; y < 3; y++) {
|
||||
norg[1] = oorg[1] + ((y==2)?-1:y)*0.0125;
|
||||
|
||||
tracebox(norg, self.mins, self.maxs, norg, FALSE, self);
|
||||
tracebox(norg, self.mins, self.maxs, norg, MOVE_NORMAL, self);
|
||||
if (!trace_startsolid) {
|
||||
self.origin = norg;
|
||||
return TRUE;
|
||||
|
@ -584,7 +584,7 @@ PMove_Move(void)
|
|||
for (i = 3, move_time = input_timelength; move_time > 0 && i; i--) {
|
||||
dest = self.origin + (self.velocity * move_time);
|
||||
|
||||
tracebox(self.origin, self.mins, self.maxs, dest, FALSE, self);
|
||||
tracebox(self.origin, self.mins, self.maxs, dest, MOVE_NORMAL, self);
|
||||
|
||||
if (trace_startsolid) {
|
||||
if (!PMove_Fix_Origin()) {
|
||||
|
@ -611,7 +611,7 @@ PMove_Move(void)
|
|||
trace_endpos[2] += serverkeyfloat("phy_airstepheight");
|
||||
}
|
||||
|
||||
tracebox(self.origin, self.mins, self.maxs, trace_endpos, FALSE, self);
|
||||
tracebox(self.origin, self.mins, self.maxs, trace_endpos, MOVE_NORMAL, self);
|
||||
stepped = trace_endpos[2] - self.origin[2];
|
||||
|
||||
float roof_fraction = trace_fraction;
|
||||
|
@ -621,7 +621,7 @@ PMove_Move(void)
|
|||
dest[2] = trace_endpos[2]; /*only horizontally*/
|
||||
|
||||
/* move forwards */
|
||||
tracebox(trace_endpos, self.mins, self.maxs, dest, FALSE, self);
|
||||
tracebox(trace_endpos, self.mins, self.maxs, dest, MOVE_NORMAL, self);
|
||||
|
||||
/* if we got anywhere, make this raised-step move count */
|
||||
if (trace_fraction != 0) {
|
||||
|
@ -631,7 +631,7 @@ PMove_Move(void)
|
|||
/* move down */
|
||||
dest = trace_endpos;
|
||||
dest[2] -= stepped + 1;
|
||||
tracebox(trace_endpos, self.mins, self.maxs, dest, FALSE, self);
|
||||
tracebox(trace_endpos, self.mins, self.maxs, dest, MOVE_NORMAL, self);
|
||||
|
||||
if (trace_fraction < 1 && trace_plane_normal[2] > 0.7f) {
|
||||
move_time -= move_time * fwfrac;
|
||||
|
@ -659,7 +659,7 @@ PMove_Move(void)
|
|||
if (self.flags & FL_ONGROUND) {
|
||||
dest = self.origin;
|
||||
dest[2] -= serverkeyfloat("phy_stepheight");
|
||||
tracebox(self.origin, self.mins, self.maxs, dest, FALSE, self);
|
||||
tracebox(self.origin, self.mins, self.maxs, dest, MOVE_NORMAL, self);
|
||||
if (trace_fraction >= 1) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ BASEGAME valve
|
|||
-set gameinfo_svonly "0"
|
||||
-set gameinfo_menutrack ""
|
||||
-set gameinfo_chatroom "halflife"
|
||||
-set gameinfo_pkgname "valve_uplink;valve_realmedia;valve_patch1110;valve_opfordemo;valve_hlds;logos_realmedia"
|
||||
-set gameinfo_pkgname "valve_uplink;valve_realmedia;valve_patch1110;valve_opfordemo;valve_hlds;logos_realmedia;valve_dayone"
|
||||
|
||||
DOWNLOADSURL http://www.frag-net.com/dl/valve_packages
|
||||
UPDATEURL http://www.frag-net.com/mods/valve.fmf
|
||||
|
|
Loading…
Reference in a new issue