Skip to content

Commit

Permalink
Implement Aim Barriers (#46)
Browse files Browse the repository at this point in the history
* Implement Aim Barriers

Add new CVars: `redm_aim_barrier`, `redm_aim_barrier_always_show`.

* Add stocks `_xs_*`* better code readability

* better stock functions

* IsMapCompatible(): add desc and fix naming

* Barrier redraw task rework
  • Loading branch information
SergeyShorokhov authored Sep 26, 2023
1 parent 9ab7968 commit accad22
Show file tree
Hide file tree
Showing 6 changed files with 3,272 additions and 0 deletions.
10 changes: 10 additions & 0 deletions cstrike/addons/amxmodx/configs/redm/gamemode_deathmatch.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
"redm_spawn_preset": "preset",

// ReDM: Features
/* Enable a barrier in the middle of the map (`anti-rush' system).
It dont work on `de_`, `cs_` `css_` maps. */
"redm_aim_barrier": "1",

/* Barrier display mode
`0` - disable,
`1` - display permanently (beta),
`2` - display only when touched. */
"redm_aim_barrier_always_show": "2",

// Open equip menu by pressing `G` (drop command).
"redm_open_equip_menu_by_g": "1",

Expand Down
2 changes: 2 additions & 0 deletions cstrike/addons/amxmodx/scripting/ReDeathmatch.sma
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <reapi>
#include <redm>

#tryinclude <msgstocks>

#include "ReDeathmatch/ReDM_config.inc"
#include "ReDeathmatch/ReDM_cvars_handler.inc"
#include "ReDeathmatch/ReDM_spawn_manager.inc"
Expand Down
204 changes: 204 additions & 0 deletions cstrike/addons/amxmodx/scripting/ReDeathmatch/Features/AimBarriers.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
static const Float: BARRIER_REDRAW_TIME = 5.0

static g_spriteLaserbeam
static g_spriteBubble

static bool: redm_aim_barrier
static redm_aim_barrier_always_show

AimBarriers_Precache() {
g_spriteLaserbeam = precache_model("sprites/laserbeam.spr")
g_spriteBubble = precache_model("sprites/bubble.spr")
}

AimBarriers_Init() {
bind_pcvar_num(
create_cvar(
"redm_aim_barrier", "1",
.has_min = true, .min_val = 0.0,
.has_max = true, .max_val = 1.0,
.description = "Enable a barrier in the middle of the map (`anti-rush' system). \
It does not work on `de_`, `cs_` `css_` maps."
),
redm_aim_barrier
)
bind_pcvar_num(
create_cvar(
"redm_aim_barrier_always_show", "2",
.has_min = true, .min_val = 0.0,
.has_max = true, .max_val = 2.0,
.description = "Barrier display mode. \
`0` - disable, \
`1` - display permanently (beta), \
`2` - display only when touched."
),
redm_aim_barrier_always_show
)

new const prefixBlocklist[][] = { "de_", "cs_", "css_" }
if (!IsMapCompatible(prefixBlocklist))
return

CreateBarrier()

RegisterHam(Ham_Touch, "trigger_push", "CTriggerPush_Touch", .Post = false)
}

static CreateBarrier() {
new Float: middle[3], longerAxis
CWorld_GetCenter(middle, longerAxis)

new Float: mins[3] = { -10.0, -10.0, -8192.0 }
new Float: maxs[3] = { 10.0, 10.0, 8192.0 }

mins[!longerAxis] *= 500
maxs[!longerAxis] *= 500

new ent = CBarrier_Spawn(middle, mins, maxs, 2.0)
set_task_ex(BARRIER_REDRAW_TIME, "BarrierRedraw", ent, .flags = SetTask_Repeat)

return ent
}

static bool: GetAvgOrigin(const classname[], Float: out[3], bool: simple = false) {
new count

new ent = MaxClients
while ((ent = fm_find_ent_by_class(ent, classname))) {
new Float: origin[3]
pev(ent, pev_origin, origin)

xs_vec_add(out, origin, out)
++count

if (simple)
break
}

if (!count)
return false

for (new i; i < sizeof out; i++) {
out[i] /= float(count)
}

return true
}

static CWorld_GetCenter(Float: out[3], &longerAxis) {
new const startEntClassname[] = "info_player_deathmatch"
new const endEntClassname[] = "info_player_start"

new Float: start[3], Float: end[3]
GetAvgOrigin(startEntClassname, start)
GetAvgOrigin(endEntClassname, end)

_xs_vec_lerp(start, end, out, 0.5)

longerAxis = floatabs(out[XS_X] - start[XS_X]) < floatabs(out[XS_Y] - start[XS_Y])

set_pev(0, pev_origin, out, sizeof(out)) // TODO: hacky ?!
}

static CBarrier_Spawn(const Float: origin[3], const Float: mins[3], const Float: maxs[3], const Float: pushForce = 2.0) {
new ent = fm_create_entity("trigger_push")
set_pev(ent, pev_origin, origin)
set_pev(ent, pev_speed, -pushForce)

dllfunc(DLLFunc_Spawn, ent)
engfunc(EngFunc_SetSize, ent, mins, maxs)

return ent
}

public CTriggerPush_Touch(const entity, const other) {
if (!IsActive())
return HAM_SUPERCEDE

if (pev_valid(other) != 2)
return HAM_IGNORED

return CBarrier_Touch(entity, other)
}

static CBarrier_Touch(const entity, const other) {
if (!redm_aim_barrier)
return HAM_SUPERCEDE

static Float: velocity[3]
pev(other, pev_velocity, velocity)

set_pev(entity, pev_movedir, velocity)

if (redm_aim_barrier_always_show == 2) {
new Float: gameTime = get_gametime()

static Float: nextEffctsTime
if (nextEffctsTime > gameTime)
return HAM_IGNORED

const Float: drawDelay = 0.5
nextEffctsTime = gameTime + drawDelay

CBarrier_Draw(entity, other, drawDelay)
}

return HAM_IGNORED
}

static CBarrier_Draw(const entity, const toucher, const Float: drawDelay) {
static Float: origin[3]
pev(entity, pev_origin, origin)

static Float: tourcherOrigin[3]
tourcherOrigin = origin
if (toucher) {
pev(toucher, pev_absmin, tourcherOrigin)
tourcherOrigin[XS_Z] += 10
}

static Float: mins[3]
pev(entity, pev_mins, mins)

static Float: maxs[3]
pev(entity, pev_maxs, maxs)

static Float: start[3]
xs_vec_copy(origin, start)

static Float: end[3]
xs_vec_copy(origin, end)

new longerAxis = floatabs(origin[XS_X] - mins[XS_X]) > floatabs(origin[XS_Y] - mins[XS_Y])

start[!longerAxis] -= mins[!longerAxis]
end[!longerAxis] -= maxs[!longerAxis]
start[XS_Z] = end[XS_Z] = ((tourcherOrigin[XS_Z]) + (mins[XS_Z] * 2))

new s[3], e[3]
FVecIVec(start, s)
FVecIVec(end, e)

new Float: overlap = 0.0 // -0.8
new lifeTime = floatround((drawDelay + overlap) * 10, floatround_ceil)
te_create_beam_between_points(
s, e,
g_spriteLaserbeam,
0,
30,
lifeTime,
255,
.r = 100, .g = 0, .b = 0,
.speed = 3,
.noise = 0
)

te_create_bubble_line(s, e, g_spriteBubble, 255, .height = 1000, .randomness = true)
}

public BarrierRedraw(const entity) {
if (redm_aim_barrier_always_show != 1)
return

CBarrier_Draw(entity, 0, BARRIER_REDRAW_TIME)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "ReDeathmatch/Features/AimBarriers.inc"

static g_fwdPrecacheEvent = -1
static g_gunsEventsId
static g_oldGroupinfo[MAX_PLAYERS + 1]
Expand All @@ -19,6 +21,8 @@ static redm_protection_color_ct[32]
static bool: mp_respawn_immunity_effects

Features_Precache() {
AimBarriers_Precache()

g_fwdPrecacheEvent = register_forward(FM_PrecacheEvent , "PrecacheEvent_Post", ._post = true)
}

Expand All @@ -40,6 +44,8 @@ Features_Init() {
RegisterHookChain(RG_CBasePlayer_RemoveSpawnProtection, "CBasePlayer_RemoveSpawnProtection", .post = true)
RegisterHookChain(RG_CBasePlayer_DropPlayerItem, "CBasePlayer_DropPlayerItem", .post = false)

AimBarriers_Init()

bind_pcvar_num(
create_cvar(
"redm_open_equip_menu_by_g", "1",
Expand Down
Loading

0 comments on commit accad22

Please sign in to comment.