Skip to content

Commit 057d19a

Browse files
committed
prototype hardpoint ai
1 parent 43bf6cb commit 057d19a

File tree

13 files changed

+489
-67
lines changed

13 files changed

+489
-67
lines changed

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ members = [
66
]
77

88
[workspace.dependencies]
9-
# rrplug = { path = "../rrplug" }
9+
rrplug = { path = "../rrplug" }
1010
shared = { path = "shared" }
11-
rrplug = { git = "https://github.com/catornot/rrplug.git" }
11+
# rrplug = { git = "https://github.com/catornot/rrplug.git" }
1212
rustc_version = "0.4.1"
1313
windows-sys = { version = "0.48.0", features = ["Win32_System_LibraryLoader", "Win32_Foundation", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_Threading"] }
1414
itertools = "0.14.*"

bp_ort/src/bots/cmds/hardpoint.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,8 @@ fn try_refresh_hardpoint(helper: &CUserCmdHelper) -> EngineToken {
213213
data.hardpoints.clear();
214214

215215
data.hardpoints.extend(
216-
get_ents_by_class_name(c"info_hardpoint", helper.sv_funcs).map(|ent| unsafe {
217-
*ent.cast::<CPlayer>()
218-
.as_ref()
219-
.unwrap_unchecked()
220-
.get_origin(&mut v)
221-
}),
216+
get_ents_by_class_name(c"info_hardpoint", helper.sv_funcs)
217+
.map(|ent| unsafe { *ent.as_ref().unwrap_unchecked().get_origin(&mut v) }),
222218
);
223219

224220
token

bp_ort/src/bots/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ mod netvars;
5353
mod set_on_join;
5454
mod simple_bot_manager;
5555

56-
pub const DEFAULT_SIMULATE_TYPE: i32 = 6;
56+
pub const DEFAULT_SIMULATE_TYPE: i32 = 100;
5757

5858
static BASE_AIM_PENALTY: OnceCell<ConVarStruct> = OnceCell::new();
5959
static CLAN_TAG_CONVAR: OnceCell<ConVarStruct> = OnceCell::new();

octbots/src/behavior.rs

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ use bevy_math::UVec3;
22
use bonsai_bt::{
33
Action,
44
Behavior::{AlwaysSucceed, If, Select, WhenAny},
5-
Event, Sequence, Status, UpdateArgs, BT, RUNNING,
5+
Event, Sequence,
6+
Status::{self},
7+
UpdateArgs, BT, RUNNING,
68
};
79
use itertools::Itertools;
810
use oktree::prelude::*;
9-
use parking_lot::RwLock;
11+
use parking_lot::{Mutex, RwLock};
1012
use rrplug::{
1113
bindings::class_types::{cbaseentity::CBaseEntity, client::CClient, cplayer::CPlayer},
1214
prelude::*,
@@ -17,22 +19,31 @@ use shared::{
1719
utils::{get_player_index, is_alive, lookup_ent, nudge_type, trace_ray},
1820
};
1921
use std::{
20-
collections::{BTreeMap, BTreeSet, HashMap, VecDeque},
22+
collections::{BTreeSet, HashMap, VecDeque},
2123
sync::{Arc, LazyLock},
2224
};
2325

2426
use crate::{
2527
async_pathfinding::{GoalFloat, PathReceiver},
28+
gamemode_cp::{run_cp, GamemodeCP, GamemodeCPAction, SharedGamemodeCP},
2629
loader::{Navmesh, NavmeshStatus, Octree32},
2730
movement::{run_movement, Movement, MovementAction},
2831
nav_points::{tuvec_to_vector3, vector3_to_tuvec, NavPoint},
29-
pathfinding::{find_path, AreaCost, Goal},
30-
targeting::{run_targeting, Target, Targeting, TargetingAction},
32+
pathfinding::{find_path, Goal},
33+
targeting::{run_targeting, Targeting, TargetingAction},
3134
};
3235

3336
static BEHAVIOR: LazyLock<RwLock<HashMap<u16, BT<BotAction, BotBrain>>>> =
3437
LazyLock::new(|| RwLock::new(HashMap::new()));
38+
static SHARED: LazyLock<Arc<Mutex<SharedBotBrain>>> =
39+
LazyLock::new(|| Arc::new(Mutex::new(SharedBotBrain::default())));
3540

41+
#[derive(Debug, Clone, Default)]
42+
pub struct SharedBotBrain {
43+
pub cp: SharedGamemodeCP,
44+
}
45+
46+
#[derive(Debug, Clone)]
3647
pub struct BotBrain {
3748
pub navmesh: Arc<RwLock<Navmesh>>,
3849
pub path_receiver: Option<PathReceiver>,
@@ -45,10 +56,13 @@ pub struct BotBrain {
4556
pub last_alive_state: bool,
4657
pub looked_at_death_record: bool,
4758
pub needs_new_path: bool,
59+
gamemode: String,
60+
pub shared: Arc<Mutex<SharedBotBrain>>,
4861

4962
/// movement
5063
pub m: Movement,
5164
pub t: Targeting,
65+
pub cp: GamemodeCP,
5266
}
5367

5468
#[derive(Debug, Clone)]
@@ -60,10 +74,13 @@ pub enum BotAction {
6074
DeadState,
6175
Movement(MovementAction),
6276
Targeting(TargetingAction),
77+
GamemodeCP(GamemodeCPAction),
78+
IsGamemode(&'static str),
6379
}
6480

6581
pub fn drop_behaviors() {
6682
BEHAVIOR.write().clear();
83+
*SHARED.lock() = Default::default();
6784
}
6885

6986
pub extern "C" fn init_bot(edict: u16, client: &CClient) {
@@ -104,6 +121,15 @@ pub extern "C" fn init_bot(edict: u16, client: &CClient) {
104121
Action(TargetingAction::TargetSwitching.into()),
105122
]);
106123

124+
let gamemode_cp = AlwaysSucceed(Box::new(Sequence(vec![
125+
Select(vec![
126+
Action(BotAction::IsGamemode("cp")),
127+
Action(BotAction::IsGamemode("mcp")),
128+
]),
129+
Action(GamemodeCPAction::UpdateGamemodeState.into()),
130+
Action(GamemodeCPAction::DetermineTarget.into()),
131+
])));
132+
107133
let target_tracking = Sequence(vec![
108134
Action(TargetingAction::FindTarget.into()),
109135
Action(BotAction::RenderPath),
@@ -118,8 +144,17 @@ pub extern "C" fn init_bot(edict: u16, client: &CClient) {
118144
Action(BotAction::CheckNavmesh),
119145
If(
120146
Box::new(Action(BotAction::IsDead)),
121-
Box::new(Action(BotAction::DeadState)),
122-
Box::new(target_tracking),
147+
Box::new(Sequence(vec![
148+
Action(BotAction::DeadState),
149+
Select(vec![Sequence(vec![
150+
Select(vec![
151+
Action(BotAction::IsGamemode("cp")),
152+
Action(BotAction::IsGamemode("mcp")),
153+
]),
154+
Action(GamemodeCPAction::RemoveTarget.into()),
155+
])]),
156+
])),
157+
Box::new(Sequence(vec![gamemode_cp, target_tracking])),
123158
),
124159
]);
125160

@@ -141,29 +176,15 @@ pub extern "C" fn init_bot(edict: u16, client: &CClient) {
141176
angles: Vector3::ZERO,
142177
abs_origin: Vector3::ZERO,
143178
needs_new_path: true,
179+
gamemode: String::new(),
180+
181+
t: Targeting::default(),
182+
183+
m: Movement::default(),
184+
185+
cp: GamemodeCP::default(),
144186

145-
t: Targeting {
146-
current_target: Target::None,
147-
last_target: Target::None,
148-
reacts_at: 0.,
149-
spread: Vec::new(),
150-
spread_rigth: true,
151-
hates: BTreeMap::default(),
152-
},
153-
154-
m: Movement {
155-
can_move: true,
156-
next_wall_point: None,
157-
next_point_override: None,
158-
view_lock: false,
159-
clamped_view: Some(0.),
160-
jump_tick: 0,
161-
vault_tick: 0,
162-
down_tick: 0,
163-
area_cost: AreaCost::default(),
164-
last_path_points: Vec::new(),
165-
last_point_reached_delta: 0.,
166-
},
187+
shared: Arc::clone(&*SHARED),
167188
},
168189
));
169190
}
@@ -193,6 +214,10 @@ pub extern "C" fn wallpathfining_bots(helper: &CUserCmdHelper, bot: &mut CPlayer
193214
bt.blackboard_mut().origin = unsafe { *bot.get_origin(&mut v) };
194215
bt.blackboard_mut().angles = unsafe { *bot.eye_angles(&mut v) };
195216
bt.blackboard_mut().abs_origin = bot.m_vecAbsOrigin;
217+
bt.blackboard_mut().gamemode =
218+
ConVarStruct::find_convar_by_name("mp_gamemode", unsafe { EngineToken::new_unchecked() })
219+
.map(|convar| convar.get_value_string())
220+
.unwrap_or_default();
196221

197222
if is_alive(bot) != bt.blackboard().last_alive_state {
198223
bt.reset_bt();
@@ -341,11 +366,8 @@ pub extern "C" fn wallpathfining_bots(helper: &CUserCmdHelper, bot: &mut CPlayer
341366

342367
(Status::Success, 0.)
343368
}
344-
345369
BotAction::Movement(movement) => run_movement(movement, brain, bot, helper),
346-
347370
BotAction::Targeting(targeting) => run_targeting(targeting, brain, bot, helper),
348-
349371
BotAction::IsDead => {
350372
if brain.last_alive_state {
351373
brain.looked_at_death_record = false;
@@ -354,7 +376,6 @@ pub extern "C" fn wallpathfining_bots(helper: &CUserCmdHelper, bot: &mut CPlayer
354376
(Status::Success, 0.)
355377
}
356378
}
357-
358379
BotAction::DeadState => {
359380
brain.needs_new_path = true;
360381
// this a bit dangerous since if FindPath is running in parallel it can cause lot's of tasks to get pushed to the worker threads which will overwhelm them
@@ -371,6 +392,14 @@ pub extern "C" fn wallpathfining_bots(helper: &CUserCmdHelper, bot: &mut CPlayer
371392

372393
(Status::Success, 0.)
373394
}
395+
BotAction::IsGamemode(gamemode) => {
396+
if &brain.gamemode == gamemode {
397+
(Status::Success, 0.)
398+
} else {
399+
(Status::Failure, 0.)
400+
}
401+
}
402+
BotAction::GamemodeCP(gamemode_cp) => run_cp(gamemode_cp, brain, bot, helper),
374403
});
375404

376405
if bt.is_finished() {

0 commit comments

Comments
 (0)