Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions codxe.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<ClCompile Include="src\game\iw3\mp\components\mpsp.cpp" />
<ClCompile Include="src\game\iw3\mp\components\scr_parser.cpp" />
<ClCompile Include="src\game\iw3\mp\components\scr_vm_functions.cpp" />
<ClCompile Include="src\game\iw3\mp\components\sv_bots.cpp" />
<ClCompile Include="src\game\iw3\mp\main.cpp" />

<ClCompile Include="src\game\iw3\sp\components\scr_parser.cpp" />
Expand Down
30 changes: 29 additions & 1 deletion resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc
Original file line number Diff line number Diff line change
Expand Up @@ -2753,6 +2753,7 @@ generateMenuOptions()
self addMenuOption("bot_action_menu", "Auto Mantle ON/OFF", ::toggleAutoMantle);
self addMenuOption("bot_action_menu", "Trigger Distance UP", ::modifyTriggerDistance, 10);
self addMenuOption("bot_action_menu", "Trigger Distance DOWN", ::modifyTriggerDistance, -10);
self addMenuOption("bot_action_menu", "Toggle stance", ::CycleBotStance);
}

// Player model menu
Expand All @@ -2777,6 +2778,31 @@ generateMenuOptions()
self addMenuOption("graphics_menu", "Toggle Greenscreen", ::toggleGreenscreen);
}

CycleBotStance()
{
bot = self.cj["bots"][self.cj["botnumber"]];
if(!isdefined(bot))
{
self iprintln("^1bot not found.");
return;
}

stance = bot GetStance();
if (stance == "stand")
{
bot botaction("+gocrouch");
}
else if (stance == "crouch")
{
bot botaction("-gocrouch");
bot botaction("+goprone");
}
else if (stance == "prone")
{
bot botaction("-goprone"); // returns to stand
}
}

toggleRpgLookdown()
{
if (!isdefined(self.cj["settings"]["tas_rpg_lookdown"]))
Expand Down Expand Up @@ -3242,12 +3268,14 @@ startAutoMantle()
{
if (distance(botEye, self getorigin()) < self.triggerDistance)
{
bot botjump();
bot botaction("+gostand");
self waittill("position_loaded");
// wait for bot to finish mantling before loading position
if (bot ismantling())
wait 0.5;

bot botstop();

bot loadPos(0);
}
wait 0.05;
Expand Down
134 changes: 134 additions & 0 deletions src/game/iw3/mp/components/sv_bots.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "pch.h"
#include "g_scr_main.h"
#include "sv_bots.h"

#define KEY_MASK_FIRE 1
#define KEY_MASK_SPRINT 2
#define KEY_MASK_MELEE 4
#define KEY_MASK_RELOAD 16
#define KEY_MASK_LEANLEFT 64
#define KEY_MASK_LEANRIGHT 128
#define KEY_MASK_PRONE 256
#define KEY_MASK_CROUCH 512
#define KEY_MASK_JUMP 1024
#define KEY_MASK_ADS_MODE 2048
#define KEY_MASK_TEMP_ACTION 4096
#define KEY_MASK_HOLDBREATH 8192
#define KEY_MASK_FRAG 16384
#define KEY_MASK_SMOKE 32768
#define KEY_MASK_NIGHTVISION 262144
#define KEY_MASK_ADS 524288
#define KEY_MASK_USE 8
#define KEY_MASK_USERELOAD 32
#define BUTTON_ATTACK KEY_MASK_FIRE
#define MAX_CLIENTS 18

namespace iw3
{
namespace mp
{

struct BotMovementInfo_t
{
int buttons;
};

BotMovementInfo_t g_botai[MAX_CLIENTS];

Detour SV_BotUserMove_Detour;
void SV_BotUserMove_Stub(client_t *cl)
{
if (!cl->gentity)
return;

const int clientNum = cl - svsHeader->clients;

usercmd_s cmd;
memset(&cmd, 0, sizeof(cmd));

cmd.serverTime = svsHeader->time;

const playerState_s *ps = SV_GameClientNum(clientNum);
cmd.weapon = (unsigned char)ps->weapon;

if (g_clients[clientNum].sess.archiveTime == 0)
{
cmd.buttons = g_botai[clientNum].buttons;
}

cl->header.deltaMessage = cl->header.netchan.outgoingSequence - 1;
SV_ClientThink(cl, &cmd);
}

struct BotAction_t
{
const char *action;
int key;
};

const BotAction_t BotActions[] = {{"gostand", KEY_MASK_JUMP}, {"gocrouch", KEY_MASK_CROUCH},
{"goprone", KEY_MASK_PRONE}, {"fire", KEY_MASK_FIRE},
{"melee", KEY_MASK_MELEE}, {"frag", KEY_MASK_FRAG},
{"smoke", KEY_MASK_SMOKE}, {"reload", KEY_MASK_RELOAD},
{"sprint", KEY_MASK_SPRINT}, {"leanleft", KEY_MASK_LEANLEFT},
{"leanright", KEY_MASK_LEANRIGHT}, {"ads", KEY_MASK_ADS_MODE | KEY_MASK_ADS},
{"holdbreath", KEY_MASK_HOLDBREATH}, {"activate", KEY_MASK_USE}};

static void Scr_BotAction(scr_entref_t entref)
{
GetPlayerEntity(entref);

if (Scr_GetNumParam() != 1)
Scr_Error("Usage: <bot> botAction(<action>);");

const char *action = Scr_GetString(0);

if (action[0] != '+' && action[0] != '-')
Scr_ParamError(0, "Sign for bot action must be '+' or '-'.");

bool key_found = false;
for (size_t i = 0; i < ARRAYSIZE(g_botai); ++i)
{
if (!stricmp(&action[1], BotActions[i].action))
{
key_found = true;
if (action[0] == '+')
g_botai[entref.entnum].buttons |= BotActions[i].key;
else
g_botai[entref.entnum].buttons &= ~(BotActions[i].key);

return;
}
}

if (!key_found)
{
Scr_ParamError(0, va("Unknown bot action."));
}
}

static void Scr_BotStop(scr_entref_t entref)
{
GetPlayerEntity(entref);

if (Scr_GetNumParam() != 0)
Scr_Error("Usage: <bot> botStop();");

g_botai[entref.entnum].buttons = 0;
}

sv_bots::sv_bots()
{
SV_BotUserMove_Detour = Detour(SV_BotUserMove, SV_BotUserMove_Stub);
SV_BotUserMove_Detour.Install();

Scr_AddMethod("botaction", Scr_BotAction, 0);
Scr_AddMethod("botstop", Scr_BotStop, 0);
}

sv_bots::~sv_bots()
{
SV_BotUserMove_Detour.Remove();
}
} // namespace mp
} // namespace iw3
21 changes: 21 additions & 0 deletions src/game/iw3/mp/components/sv_bots.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "pch.h"

namespace iw3
{
namespace mp
{
class sv_bots : public Module
{
public:
sv_bots();
~sv_bots();

const char *get_name() override
{
return "sv_bots";
};
};
} // namespace mp
} // namespace iw3
53 changes: 2 additions & 51 deletions src/game/iw3/mp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "components/pm.h"
#include "components/scr_parser.h"
#include "components/scr_vm_functions.h"
#include "components/sv_bots.h"
#include "common/config.h"

// Structure to hold data for the active keyboard request
Expand Down Expand Up @@ -1373,51 +1374,6 @@ void UI_Refresh_Hook(int localClientNum)
CheckKeyboardCompletion();
}

struct BotAction
{
bool jump;
};

// map of client index to bot action
std::map<int, BotAction> botActions;

void GScr_BotJump(scr_entref_t entref)
{
client_t *cl = &svsHeader->clients[entref.entnum];

if (cl->header.state && cl->header.netchan.remoteAddress.type == NA_BOT)
{
botActions[entref.entnum].jump = true;
}
}

Detour SV_ClientThinkDetour;

// TODO: maybe recreate the original and call it in the hook
void SV_ClientThinkHook(client_t *cl, usercmd_s *cmd)
{
// Check if the client is a bot
if (cl->header.state && cl->header.netchan.remoteAddress.type == NA_BOT)
{
// Reset bot's movement and actions set in SV_BotUserMove
cmd->forwardmove = 0;
cmd->rightmove = 0;
cmd->buttons = 0;

int clientIndex = cl - svsHeader->clients;
if (botActions.find(clientIndex) != botActions.end())
{
if (botActions[clientIndex].jump)
{
cmd->buttons = 1024; // BUTTON_JUMP
botActions[clientIndex].jump = false;
}
}
}

SV_ClientThinkDetour.GetOriginal<decltype(SV_ClientThink)>()(cl, cmd);
}

Detour Pmove_Detour;

// https://github.com/kejjjjj/iw3sptool/blob/17b669233a1ad086deed867469dc9530b84c20e6/iw3sptool/bg/bg_pmove.cpp#L11
Expand Down Expand Up @@ -1492,6 +1448,7 @@ IW3_MP_Plugin::IW3_MP_Plugin()
RegisterModule(new mpsp());
RegisterModule(new scr_parser());
RegisterModule(new scr_vm_functions());
RegisterModule(new sv_bots());

UI_Refresh_Detour = Detour(UI_Refresh, UI_Refresh_Hook);
UI_Refresh_Detour.Install();
Expand All @@ -1517,11 +1474,6 @@ IW3_MP_Plugin::IW3_MP_Plugin()
cmd_function_s *cmdinput_VAR = new cmd_function_s;
Cmd_AddCommandInternal("cmdinput", Cmd_cmdinput_f, cmdinput_VAR);

Scr_AddMethod("botjump", GScr_BotJump, 0);

SV_ClientThinkDetour = Detour(SV_ClientThink, SV_ClientThinkHook);
SV_ClientThinkDetour.Install();

Dvar_RegisterBool("pm_fixed_fps_enable", false, 0, "Enable fixed FPS mode");
Dvar_RegisterInt("pm_fixed_fps", 250, 0, 1000, 0, "Fixed FPS value");
Pmove_Detour = Detour(Pmove, Pmove_Hook);
Expand All @@ -1540,7 +1492,6 @@ IW3_MP_Plugin::~IW3_MP_Plugin()
Load_MapEntsPtr_Detour.Remove();
R_StreamLoadFileSynchronously_Detour.Remove();

SV_ClientThinkDetour.Remove();
Pmove_Detour.Remove();
}

Expand Down