Fixed inablity to delete paths between nodes.
Some fixes to facing node index search.
This commit is contained in:
parent
d011aa6551
commit
2f4b329ad1
4 changed files with 105 additions and 40 deletions
|
|
@ -47,18 +47,12 @@ public:
|
||||||
// gets the build number of bot
|
// gets the build number of bot
|
||||||
int buildNumber ();
|
int buildNumber ();
|
||||||
|
|
||||||
// gets the shooting cone deviation
|
|
||||||
float getShootingCone (edict_t *ent, const Vector &position);
|
|
||||||
|
|
||||||
// check if origin is visible from the entity side
|
// check if origin is visible from the entity side
|
||||||
bool isVisible (const Vector &origin, edict_t *ent);
|
bool isVisible (const Vector &origin, edict_t *ent);
|
||||||
|
|
||||||
// check if entity is alive
|
// check if entity is alive
|
||||||
bool isAlive (edict_t *ent);
|
bool isAlive (edict_t *ent);
|
||||||
|
|
||||||
// check if origin is inside view cone of entity
|
|
||||||
bool isInViewCone (const Vector &origin, edict_t *ent);
|
|
||||||
|
|
||||||
// checks if entitiy is fakeclient
|
// checks if entitiy is fakeclient
|
||||||
bool isFakeClient (edict_t *ent);
|
bool isFakeClient (edict_t *ent);
|
||||||
|
|
||||||
|
|
@ -142,6 +136,16 @@ public:
|
||||||
return m_sendToHook.enable ();
|
return m_sendToHook.enable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gets the shooting cone deviation
|
||||||
|
float getShootingCone (edict_t *ent, const Vector &position) {
|
||||||
|
return ent->v.v_angle.forward () | (position - (ent->v.origin + ent->v.view_ofs)).normalize (); // he's facing it, he meant it
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if origin is inside view cone of entity
|
||||||
|
bool isInViewCone (const Vector &origin, edict_t *ent) {
|
||||||
|
return getShootingCone (ent, origin) >= cr::cosf (cr::degreesToRadians ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static int32 CR_STDCALL sendTo (int socket, const void *message, size_t length, int flags, const struct sockaddr *dest, int destLength);
|
static int32 CR_STDCALL sendTo (int socket, const void *message, size_t length, int flags, const struct sockaddr *dest, int destLength);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1496,7 +1496,7 @@ void Bot::buyStuff () {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BuyState::SecondaryWeapon: // if bot has still some money, buy a better secondary weapon
|
case BuyState::SecondaryWeapon: // if bot has still some money, buy a better secondary weapon
|
||||||
if (isPistolMode || (isFirstRound && hasDefaultPistols) || (hasDefaultPistols && bots.getLastWinner () != m_team) || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg.int_ (7500, 9000))) {
|
if (isPistolMode || (isFirstRound && hasDefaultPistols) || (hasDefaultPistols && bots.getLastWinner () != m_team) || (hasPrimaryWeapon () && hasDefaultPistols) && m_moneyAmount > rg.int_ (7500, 9000)) {
|
||||||
do {
|
do {
|
||||||
pref--;
|
pref--;
|
||||||
|
|
||||||
|
|
|
||||||
119
source/graph.cpp
119
source/graph.cpp
|
|
@ -532,6 +532,8 @@ IntArray BotGraph::searchRadius (float radius, const Vector &origin, int maxCoun
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotGraph::add (int type, const Vector &pos) {
|
void BotGraph::add (int type, const Vector &pos) {
|
||||||
|
// @todo: remove type magic numbers
|
||||||
|
|
||||||
if (game.isNullEntity (m_editor)) {
|
if (game.isNullEntity (m_editor)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -547,6 +549,22 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
m_hasChanged = true;
|
m_hasChanged = true;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case 5:
|
||||||
|
index = getEditorNeareset ();
|
||||||
|
|
||||||
|
if (index != kInvalidNodeIndex) {
|
||||||
|
path = &m_paths[index];
|
||||||
|
|
||||||
|
if (path->flags & NodeFlag::Camp) {
|
||||||
|
path->start = m_editor->v.v_angle.get2d ();
|
||||||
|
|
||||||
|
// play "done" sound...
|
||||||
|
game.playSound (m_editor, "common/wpn_hudon.wav");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
index = getEditorNeareset ();
|
index = getEditorNeareset ();
|
||||||
|
|
||||||
|
|
@ -607,6 +625,14 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addNewNode) {
|
if (addNewNode) {
|
||||||
|
auto nearest = getEditorNeareset ();
|
||||||
|
|
||||||
|
// do not allow to place waypoints "inside" waypoints, make at leat 10 units range
|
||||||
|
if (exists (nearest) && (m_paths[nearest].origin - newOrigin).lengthSq () < cr::square (10.0f)) {
|
||||||
|
ctrl.msg ("Can't add node. It's way to near to %d node. Please move some units anywhere.", nearest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// need to remove limit?
|
// need to remove limit?
|
||||||
if (m_paths.length () >= kMaxNodes) {
|
if (m_paths.length () >= kMaxNodes) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -879,33 +905,57 @@ bool BotGraph::isConnected (int a, int b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int BotGraph::getFacingIndex () {
|
int BotGraph::getFacingIndex () {
|
||||||
// this function finds node the user is pointing at.
|
// this function finds node the user is pointing at. big thanks to podbot_mm for this stuff
|
||||||
|
|
||||||
int indexToPoint = kInvalidNodeIndex;
|
int indexToPoint = kInvalidNodeIndex;
|
||||||
|
|
||||||
Array <float> cones;
|
Array <float> cones (5);
|
||||||
float maxCone = 0.0f;
|
float maxCone = 0.0f;
|
||||||
|
|
||||||
|
// list of around waypoints
|
||||||
|
auto around = searchRadius (500.0f, m_editor->v.origin);
|
||||||
|
|
||||||
// find the node the user is pointing at
|
// find the node the user is pointing at
|
||||||
for (const auto &path : m_paths) {
|
for (const auto &node : around) {
|
||||||
if ((path.origin - m_editor->v.origin).lengthSq () > cr::square (500.0f)) {
|
const auto &path = m_paths[node];
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cones.clear ();
|
cones.clear ();
|
||||||
|
|
||||||
|
// is crouch node?
|
||||||
|
bool crouchNode = !!(path.flags & NodeFlag::Crouch);
|
||||||
|
|
||||||
// get the current view cones
|
// get the current view cones
|
||||||
cones.push (util.getShootingCone (m_editor, path.origin));
|
cones.push (util.getShootingCone (m_editor, path.origin));
|
||||||
cones.push (util.getShootingCone (m_editor, path.origin - Vector (0.0f, 0.0f, (path.flags & NodeFlag::Crouch) ? 6.0f : 12.0f)));
|
cones.push (util.getShootingCone (m_editor, path.origin - Vector (0.0f, 0.0f, crouchNode ? 6.0f : 12.0f)));
|
||||||
cones.push (util.getShootingCone (m_editor, path.origin - Vector (0.0f, 0.0f, (path.flags & NodeFlag::Crouch) ? 12.0f : 24.0f)));
|
cones.push (util.getShootingCone (m_editor, path.origin - Vector (0.0f, 0.0f, crouchNode ? 12.0f : 24.0f)));
|
||||||
cones.push (util.getShootingCone (m_editor, path.origin + Vector (0.0f, 0.0f, (path.flags & NodeFlag::Crouch) ? 6.0f : 12.0f)));
|
cones.push (util.getShootingCone (m_editor, path.origin + Vector (0.0f, 0.0f, crouchNode ? 6.0f : 12.0f)));
|
||||||
cones.push (util.getShootingCone (m_editor, path.origin + Vector (0.0f, 0.0f, (path.flags & NodeFlag::Crouch) ? 12.0f : 24.0f)));
|
cones.push (util.getShootingCone (m_editor, path.origin + Vector (0.0f, 0.0f, crouchNode ? 12.0f : 24.0f)));
|
||||||
|
|
||||||
// check if we can see it
|
constexpr float minCone = 0.9992f;
|
||||||
for (auto &cone : cones) {
|
|
||||||
if (cone > 1.000f && cone > maxCone) {
|
// break if cone is bad
|
||||||
maxCone = cone;
|
if (cones[0] < minCone && cones[1] < minCone && cones[2] < minCone && cones[3] < minCone && cones[4] < minCone) {
|
||||||
indexToPoint = path.number;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whe're we're looking
|
||||||
|
if (cones[0] > maxCone || cones[1] > maxCone || cones[2] > maxCone || cones[3] > maxCone || cones[4] > maxCone) {
|
||||||
|
if (cones[0] > cones[1] && cones[0] > cones[3]) {
|
||||||
|
maxCone = cones[0];
|
||||||
}
|
}
|
||||||
|
else if (cones[1] > cones[0] && cones[1] > cones[2]) {
|
||||||
|
maxCone = cones[1];
|
||||||
|
}
|
||||||
|
else if (cones[2] > cones[1] && cones[2] > cones[4]) {
|
||||||
|
maxCone = cones[2];
|
||||||
|
}
|
||||||
|
else if (cones[3] > cones[0] && cones[3] > cones[4]) {
|
||||||
|
maxCone = cones[3];
|
||||||
|
}
|
||||||
|
else if (cones[4] > cones[3] && cones[4] > cones[2]) {
|
||||||
|
maxCone = cones[4];
|
||||||
|
}
|
||||||
|
indexToPoint = path.number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return indexToPoint;
|
return indexToPoint;
|
||||||
|
|
@ -958,7 +1008,6 @@ void BotGraph::erasePath () {
|
||||||
// this function allow player to manually remove a path from one node to another
|
// this function allow player to manually remove a path from one node to another
|
||||||
|
|
||||||
int nodeFrom = getEditorNeareset ();
|
int nodeFrom = getEditorNeareset ();
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (nodeFrom == kInvalidNodeIndex) {
|
if (nodeFrom == kInvalidNodeIndex) {
|
||||||
ctrl.msg ("Unable to find nearest node in 50 units.");
|
ctrl.msg ("Unable to find nearest node in 50 units.");
|
||||||
|
|
@ -976,9 +1025,19 @@ void BotGraph::erasePath () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper
|
||||||
|
auto destroy = [] (PathLink &link) -> void {
|
||||||
|
link.index = kInvalidNodeIndex;
|
||||||
|
link.distance = 0;
|
||||||
|
link.flags = 0;
|
||||||
|
link.velocity = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
game.print ("trying delete f = %d to %d", nodeFrom, nodeTo);
|
||||||
|
|
||||||
for (auto &link : m_paths[nodeFrom].links) {
|
for (auto &link : m_paths[nodeFrom].links) {
|
||||||
if (link.index == nodeTo) {
|
if (link.index == nodeTo) {
|
||||||
unassignPath (nodeFrom, index);
|
destroy (link);
|
||||||
game.playSound (m_editor, "weapons/mine_activate.wav");
|
game.playSound (m_editor, "weapons/mine_activate.wav");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -986,13 +1045,11 @@ void BotGraph::erasePath () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// not found this way ? check for incoming connections then
|
// not found this way ? check for incoming connections then
|
||||||
index = nodeFrom;
|
cr::swap (nodeFrom, nodeTo);
|
||||||
nodeFrom = nodeTo;
|
|
||||||
nodeTo = index;
|
|
||||||
|
|
||||||
for (auto &link : m_paths[nodeFrom].links) {
|
for (auto &link : m_paths[nodeFrom].links) {
|
||||||
if (link.index == nodeTo) {
|
if (link.index == nodeTo) {
|
||||||
unassignPath (nodeFrom, index);
|
destroy (link);
|
||||||
game.playSound (m_editor, "weapons/mine_activate.wav");
|
game.playSound (m_editor, "weapons/mine_activate.wav");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -2160,7 +2217,7 @@ void BotGraph::frame () {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getFlagsAsStr = [&] (int index) {
|
auto getFlagsAsStr = [&] (int index) {
|
||||||
auto &path = m_paths[index];
|
const auto &path = m_paths[index];
|
||||||
bool jumpPoint = false;
|
bool jumpPoint = false;
|
||||||
|
|
||||||
// iterate through connections and find, if it's a jump path
|
// iterate through connections and find, if it's a jump path
|
||||||
|
|
@ -2179,13 +2236,23 @@ void BotGraph::frame () {
|
||||||
return buffer.chars ();
|
return buffer.chars ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto pathOriginStr = [&] (int index) {
|
||||||
|
const auto &path = m_paths[index];
|
||||||
|
|
||||||
|
static String buffer;
|
||||||
|
buffer.assignf ("(%.1f, %.1f, %.1f)", path.origin.x, path.origin.y, path.origin.z);
|
||||||
|
|
||||||
|
return buffer.chars ();
|
||||||
|
};
|
||||||
|
|
||||||
// display some information
|
// display some information
|
||||||
String graphMessage;
|
String graphMessage;
|
||||||
|
|
||||||
// show the information about that point
|
// show the information about that point
|
||||||
graphMessage.assignf ("\n\n\n\n Graph Information:\n\n"
|
graphMessage.assignf ("\n\n\n\n Graph Information:\n\n"
|
||||||
" Node %d of %d, Radius: %.1f, Light: %.1f\n"
|
" Node %d of %d, Radius: %.1f, Light: %.1f\n"
|
||||||
" Flags: %s\n\n", nearestIndex, m_paths.length () - 1, path.radius, path.light, getFlagsAsStr (nearestIndex));
|
" Flags: %s\n"
|
||||||
|
" Origin: %s\n\n", nearestIndex, m_paths.length () - 1, path.radius, path.light, getFlagsAsStr (nearestIndex), pathOriginStr (nearestIndex));
|
||||||
|
|
||||||
// if node is not changed display experience also
|
// if node is not changed display experience also
|
||||||
if (!m_hasChanged) {
|
if (!m_hasChanged) {
|
||||||
|
|
@ -2201,14 +2268,16 @@ void BotGraph::frame () {
|
||||||
if (m_cacheNodeIndex != kInvalidNodeIndex) {
|
if (m_cacheNodeIndex != kInvalidNodeIndex) {
|
||||||
graphMessage.appendf ("\n Cached Node Information:\n\n"
|
graphMessage.appendf ("\n Cached Node Information:\n\n"
|
||||||
" Node %d of %d, Radius: %.1f\n"
|
" Node %d of %d, Radius: %.1f\n"
|
||||||
" Flags: %s\n", m_cacheNodeIndex, m_paths.length (), m_paths[m_cacheNodeIndex].radius, getFlagsAsStr (m_cacheNodeIndex));
|
" Flags: %s\n"
|
||||||
|
" Origin: %s\n", m_cacheNodeIndex, m_paths.length () - 1, m_paths[m_cacheNodeIndex].radius, getFlagsAsStr (m_cacheNodeIndex), pathOriginStr (m_cacheNodeIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we need to show the facing point index
|
// check if we need to show the facing point index
|
||||||
if (m_facingAtIndex != kInvalidNodeIndex) {
|
if (m_facingAtIndex != kInvalidNodeIndex) {
|
||||||
graphMessage.appendf ("\n Facing Node Information:\n\n"
|
graphMessage.appendf ("\n Facing Node Information:\n\n"
|
||||||
" Node %d of %d, Radius: %.1f\n"
|
" Node %d of %d, Radius: %.1f\n"
|
||||||
" Flags: %s\n", m_facingAtIndex, m_paths.length (), m_paths[m_facingAtIndex].radius, getFlagsAsStr (m_facingAtIndex));
|
" Flags: %s\n"
|
||||||
|
" Origin: %s\n", m_facingAtIndex, m_paths.length () - 1, m_paths[m_facingAtIndex].radius, getFlagsAsStr (m_facingAtIndex), pathOriginStr (m_facingAtIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw entire message
|
// draw entire message
|
||||||
|
|
|
||||||
|
|
@ -77,14 +77,6 @@ bool BotUtils::isAlive (edict_t *ent) {
|
||||||
return ent->v.deadflag == DEAD_NO && ent->v.health > 0 && ent->v.movetype != MOVETYPE_NOCLIP;
|
return ent->v.deadflag == DEAD_NO && ent->v.health > 0 && ent->v.movetype != MOVETYPE_NOCLIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
float BotUtils::getShootingCone (edict_t *ent, const Vector &position) {
|
|
||||||
return ent->v.v_angle.forward () | (position - (ent->v.origin + ent->v.view_ofs)).normalize (); // he's facing it, he meant it
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BotUtils::isInViewCone (const Vector &origin, edict_t *ent) {
|
|
||||||
return getShootingCone (ent, origin) >= cr::cosf (cr::degreesToRadians ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BotUtils::isVisible (const Vector &origin, edict_t *ent) {
|
bool BotUtils::isVisible (const Vector &origin, edict_t *ent) {
|
||||||
if (game.isNullEntity (ent)) {
|
if (game.isNullEntity (ent)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue