Since I try to make Survival Mod, the first thing I started is the bots, or rather their logic of movement and attack.
At the moment I only implemented LookLogic (not fully)
This is just a preview, I think in the future I can give the bots full logic, but my plans are only related to Survival Mod, I do not consider other modes yet (FFA is currently working)
Send me PM, if you have any ideas for realizing
Watching logic
https://www.youtube.com/watch?v=RDlMABVC9Vw
Move logic
https://www.youtube.com/watch?v=N81LXQvNl3k
Animated move
https://www.youtube.com/watch?v=3brC8vSBS1w
Implemeted:
- Look logic (default target player with num 0)
- Move logic (default target player with num 0) IF BOT SEE YOU
- Animated movement
[this list will be updated]
Download movement animation added
Source:
// This is preview version
// This is only the beginning of creating bots with the logic of movement and attack,
// but first of all I want to create Survival mode, so do not expect bots that can play in TDM, FFA, DZ and other.
// I guess I would do it after creating this script
// AIBots by S3VDITO
// Ver 0.0.0.3
// Realized:
// 1 - watching for player function (not works now)
// 2 - move logic [not fully] [without check collision] (in progress...)
// 3 - animated movement
gsc.setDvar("testClients_doAttack", 0);
gsc.setDvar("testClients_doCrouch", 0);
gsc.setDvar("testClients_doMove", 0);
gsc.setDvar("testClients_doReload", 0);
gsc.setDvar("testClients_doWatchKillcam", 0);
gsc.setDvarIfUninitialized("testClients_doSpeed", 4);
global bot_speed = to_float(gsc.getDvar("testClients_doSpeed"));
global bots_list = [];
global player_target_list = [];
level.onNotify("connected", fun(args) {
var player = args[0];
print(player.getGuid().find("bot"));
if(player.getGuid().find("bot") != 0)
{
print("Player connected");
player_target_list.push_back_ref(player);
}
});
level.onNotify("prematch_done", fun(args) {
if(gsc.getDvar("g_gametype") == "dm") {
for(var entRef = 0; entRef < 18; ++entRef)
{
var tempEntBot = gsc.getEntByNum(entRef);
if(tempEntBot.getGuid().find("bot") == 0)
{
var animBody = gsc.spawn("script_model", tempEntBot.getOrigin());
animBody.setmodel("mp_body_delta_elite_assault_ab");
animBody.notsolid();
animBody.LinkTo(tempEntBot, "tag_origin", [-4, 0, -1], [-4, 0, -1]);
bots_list.push_back_ref(tempEntBot);
setInterval(fun[tempEntBot, animBody]() {
botMove(tempEntBot, gsc.getEntByNum(0), animBody);
}, 50);
setInterval(fun[animBody]() {
animBody.scriptModelPlayAnim("pb_stumble_pistol_walk_forward");
}, 1000);
}
}
}
});
def botMove(bot, target, animModel)
{
var bot_weapon_origin = bot.getTagOrigin("tag_weapon_left");
HideTestClientParts(bot);
if(LockSightTest(bot, target) == false)
{
// animModel.scriptModelPlayAnim("pb_stand_alert_pistol");
return;
}
else
{
var angle = gsc.vectorToAngles([target.getTagOrigin("j_helmet")[0] - bot_weapon_origin[0], target.getTagOrigin("j_helmet")[1] - bot_weapon_origin[1], target.getTagOrigin("j_helmet")[2] - bot_weapon_origin[2]]);
bot.setPlayerAngles(angle);
// Spaming field bug =(
//animModel.set("angles", bot.getPlayerAngles());
}
var moveTarget = target.getOrigin();
var distance = gsc.distanceSquared(moveTarget, bot.getOrigin());
if(gsc.distance(moveTarget, bot.getOrigin()) <= 64)
{
// bot_speed = 0;
}
else
{
bot_speed = to_float(gsc.getDvar("testClients_doSpeed"));
var normalize = gsc.vectorNormalize([moveTarget[0] - bot.getOrigin()[0], moveTarget[1] - bot.getOrigin()[1], moveTarget[2] - bot.getOrigin()[2]]);
bot.setOrigin([bot.getOrigin()[0] + normalize[0] * bot_speed, bot.getOrigin()[1] + normalize[1] * bot_speed, bot.getOrigin()[2] + normalize[2] * bot_speed]);
}
}
def HideTestClientParts(bot)
{
bot.hidepart("j_ankle_le");
bot.hidepart("j_hiptwist_le");
bot.hidepart("j_head");
bot.hidepart("j_helmet");
bot.hidepart("j_eyeball_le");
bot.hidepart("j_clavicle_le");
}
// Stolen from _stinger.gsc :)
def LockSightTest(self, target)
{
var eyePos = self.GetEye();
var passed = gsc.SightTracePassed(eyePos, target.getOrigin(), false, target);
if ( passed == 1)
{
return true;
}
var front = target.GetPointInBounds(1, 0, 0);
passed = gsc.SightTracePassed( eyePos, front, false, target );
if (passed == 1)
{
return true;
}
var back = target.GetPointInBounds(-1, 0, 0);
passed = gsc.SightTracePassed( eyePos, back, false, target );
if (passed == 1)
{
return true;
}
return false;
}