Skip to content

Commit 890d004

Browse files
committed
add new apis
1 parent ba30b4b commit 890d004

21 files changed

+4058
-0
lines changed

api_advanced_pushing.sma

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#pragma semicolon 1
2+
3+
#include <amxmodx>
4+
#include <hamsandwich>
5+
#include <fakemeta>
6+
#include <xs>
7+
8+
#include <api_advanced_pushing>
9+
10+
#define PLAYER_PREVENT_CLIMB (1<<5)
11+
12+
#define IS_PLAYER(%1) (%1 >= 1 && %1 <= MaxClients)
13+
14+
new Float:g_flPlayerReleaseClimbBlock[MAX_PLAYERS + 1];
15+
16+
public plugin_init() {
17+
register_plugin("[API] Advanced Pushing", "1.0.0", "Hedgehog Fog");
18+
19+
RegisterHamPlayer(Ham_Spawn, "HamHook_Player_Spawn_Post", .Post = 1);
20+
RegisterHamPlayer(Ham_Player_PostThink, "HamHook_Player_PostThink_Post", .Post = 1);
21+
}
22+
23+
public plugin_natives() {
24+
register_library("api_advanced_pushing");
25+
register_native("APS_Push", "Native_Push");
26+
register_native("APS_PushFromOrigin", "Native_PushFromOrigin");
27+
register_native("APS_PushFromBBox", "Native_PushFromBBox");
28+
}
29+
30+
public Native_Push(iPluginId, iArgc) {
31+
static pEntity = get_param(1);
32+
static Float:vecForce[3]; get_array_f(2, vecForce, sizeof(vecForce));
33+
static APS_Flags:iFlags = APS_Flags:get_param(3);
34+
@Base_Push(pEntity, vecForce, iFlags);
35+
}
36+
37+
public Native_PushFromOrigin(iPluginId, iArgc) {
38+
static pEntity; pEntity = get_param(1);
39+
static Float:flForce; flForce = get_param_f(2);
40+
static Float:vecPushOrigin[3]; get_array_f(3, vecPushOrigin, sizeof(vecPushOrigin));
41+
static APS_Flags:iFlags; iFlags = APS_Flags:get_param(4);
42+
43+
@Base_PushFromOrigin(pEntity, flForce, vecPushOrigin, iFlags);
44+
}
45+
46+
public Native_PushFromBBox(iPluginId, iArgc) {
47+
static pEntity; pEntity = get_param(1);
48+
static Float:flForce; flForce = get_param_f(2);
49+
static Float:vecAbsMin[3]; get_array_f(3, vecAbsMin, sizeof(vecAbsMin));
50+
static Float:vecAbsMax[3]; get_array_f(4, vecAbsMax, sizeof(vecAbsMax));
51+
static Float:flMinDepthRatio; flMinDepthRatio = get_param_f(5);
52+
static Float:flMaxDepthRatio; flMaxDepthRatio = get_param_f(6);
53+
static Float:flDepthInfluenceMin; flDepthInfluenceMin = get_param_f(7);
54+
static Float:flDepthInfluenceMax; flDepthInfluenceMax = get_param_f(8);
55+
static APS_Flags:iFlags; iFlags = APS_Flags:get_param(9);
56+
57+
@Base_PushFromBBox(pEntity, flForce, vecAbsMin, vecAbsMax, flMinDepthRatio, flMaxDepthRatio, flDepthInfluenceMin, flDepthInfluenceMax, iFlags);
58+
}
59+
60+
public HamHook_Player_Spawn_Post(pPlayer) {
61+
@Player_ReleaseClimbPrevention(pPlayer);
62+
}
63+
64+
public HamHook_Player_PostThink_Post(pPlayer) {
65+
if (g_flPlayerReleaseClimbBlock[pPlayer] && g_flPlayerReleaseClimbBlock[pPlayer] <= get_gametime()) {
66+
@Player_ReleaseClimbPrevention(pPlayer);
67+
}
68+
}
69+
70+
@Player_SetClimbPrevention(pPlayer, bool:bValue) {
71+
new iPlayerFlags = pev(pPlayer, pev_iuser3);
72+
73+
if (bValue) {
74+
iPlayerFlags |= PLAYER_PREVENT_CLIMB;
75+
} else {
76+
iPlayerFlags &= ~PLAYER_PREVENT_CLIMB;
77+
}
78+
79+
set_pev(pPlayer, pev_iuser3, iPlayerFlags);
80+
}
81+
82+
@Player_ReleaseClimbPrevention(this) {
83+
if (g_flPlayerReleaseClimbBlock[this]) {
84+
@Player_SetClimbPrevention(this, false);
85+
g_flPlayerReleaseClimbBlock[this] = 0.0;
86+
}
87+
}
88+
89+
@Base_Push(this, const Float:vecForce[3], APS_Flags:iFlags) {
90+
static Float:vecVelocity[3]; pev(this, pev_velocity, vecVelocity);
91+
92+
if (iFlags & APS_Flag_AddForce) {
93+
xs_vec_add(vecVelocity, vecForce, vecVelocity);
94+
} else {
95+
for (new i = 0; i < 3; ++i) {
96+
if (iFlags & APS_Flag_OverlapMode) {
97+
vecVelocity[i] = vecForce[i] ? vecForce[i] : vecVelocity[i];
98+
} else {
99+
vecVelocity[i] = vecForce[i];
100+
}
101+
}
102+
}
103+
104+
set_pev(this, pev_velocity, vecVelocity);
105+
106+
if (IS_PLAYER(this) && ~pev(this, pev_iuser3) & PLAYER_PREVENT_CLIMB) {
107+
@Player_SetClimbPrevention(this, true);
108+
g_flPlayerReleaseClimbBlock[this] = get_gametime() + 0.1;
109+
}
110+
}
111+
112+
@Base_PushFromOrigin(this, Float:flForce, Float:vecPushOrigin[3], APS_Flags:iFlags) {
113+
static Float:vecOrigin[3]; pev(this, pev_origin, vecOrigin);
114+
115+
static Float:vecForce[3];
116+
xs_vec_sub(vecOrigin, vecPushOrigin, vecForce);
117+
xs_vec_normalize(vecForce, vecForce);
118+
xs_vec_mul_scalar(vecForce, flForce, vecForce);
119+
120+
@Base_Push(this, vecForce, iFlags);
121+
}
122+
123+
@Base_PushFromBBox(
124+
this,
125+
Float:flForce,
126+
const Float:vecAbsMin[3],
127+
const Float:vecAbsMax[3],
128+
Float:flMinDepthRatio,
129+
Float:flMaxDepthRatio,
130+
Float:flDepthInfluenceMin,
131+
Float:flDepthInfluenceMax,
132+
APS_Flags:iFlags
133+
) {
134+
static Float:vecOrigin[3]; pev(this, pev_origin, vecOrigin);
135+
static Float:vecToucherAbsMin[3]; pev(this, pev_absmin, vecToucherAbsMin);
136+
static Float:vecToucherAbsMax[3]; pev(this, pev_absmax, vecToucherAbsMax);
137+
138+
// Find and check intersection point
139+
for (new iAxis = 0; iAxis < 3; ++iAxis) {
140+
if (vecOrigin[iAxis] < vecAbsMin[iAxis]) {
141+
vecOrigin[iAxis] = vecToucherAbsMax[iAxis];
142+
} else if (vecOrigin[iAxis] > vecAbsMax[iAxis]) {
143+
vecOrigin[iAxis] = vecToucherAbsMin[iAxis];
144+
}
145+
146+
if (vecAbsMin[iAxis] >= vecOrigin[iAxis]) return;
147+
if (vecAbsMax[iAxis] <= vecOrigin[iAxis]) return;
148+
}
149+
150+
new iClosestAxis = -1;
151+
new pTrace = create_tr2();
152+
static Float:vecOffset[3]; xs_vec_copy(Float:{0.0, 0.0, 0.0}, vecOffset);
153+
154+
for (new iAxis = 0; iAxis < 3; ++iAxis) {
155+
// Calculates the toucher's offset relative to the current axis
156+
static Float:flSideOffsets[2];
157+
flSideOffsets[0] = vecAbsMin[iAxis] - vecOrigin[iAxis];
158+
flSideOffsets[1] = vecAbsMax[iAxis] - vecOrigin[iAxis];
159+
160+
if (iAxis == 2 && iClosestAxis != -1) {
161+
break;
162+
}
163+
164+
for (new side = 0; side < 2; ++side) {
165+
// Check exit from current side
166+
static Float:vecTarget[3];
167+
xs_vec_copy(vecOrigin, vecTarget);
168+
vecTarget[iAxis] += flSideOffsets[side];
169+
engfunc(EngFunc_TraceMonsterHull, this, vecOrigin, vecTarget, IGNORE_MONSTERS | IGNORE_GLASS, this, pTrace);
170+
171+
static Float:flFraction;
172+
get_tr2(pTrace, TR_flFraction, flFraction);
173+
174+
// No exit, cannot push this way
175+
if (flFraction != 1.0) {
176+
flSideOffsets[side] = 0.0;
177+
}
178+
179+
if (iAxis != 2) {
180+
// Save minimum offset, but ignore zero offsets
181+
if (!vecOffset[iAxis] || (flSideOffsets[side] && floatabs(flSideOffsets[side]) < floatabs(vecOffset[iAxis]))) {
182+
vecOffset[iAxis] = flSideOffsets[side];
183+
}
184+
} else {
185+
// Priority on bottom side
186+
if (flSideOffsets[0]) {
187+
vecOffset[iAxis] = flSideOffsets[0];
188+
}
189+
}
190+
191+
// Find closest axis to push
192+
if (vecOffset[iAxis]) {
193+
if (iClosestAxis == -1 || floatabs(vecOffset[iAxis]) < floatabs(vecOffset[iClosestAxis])) {
194+
iClosestAxis = iAxis;
195+
}
196+
}
197+
}
198+
}
199+
200+
free_tr2(pTrace);
201+
202+
// Push by closest axis
203+
if (iClosestAxis == -1) return;
204+
205+
static iPushDir; iPushDir = vecOffset[iClosestAxis] > 0.0 ? 1 : -1;
206+
static Float:vecSize[3]; xs_vec_sub(vecAbsMax, vecAbsMin, vecSize);
207+
static Float:flDepthRatio; flDepthRatio = floatabs(vecOffset[iClosestAxis]) / (vecSize[iClosestAxis] / 2);
208+
209+
flDepthRatio = floatclamp(flDepthRatio, flMinDepthRatio, flMaxDepthRatio);
210+
211+
static Float:vecForce[3]; xs_vec_copy(Float:{0.0, 0.0, 0.0}, vecForce);
212+
213+
static bool:bInInfluence; bInInfluence = (
214+
flDepthRatio >= flDepthInfluenceMin &&
215+
flDepthRatio <= flDepthInfluenceMax
216+
);
217+
218+
if (bInInfluence) {
219+
vecForce[iClosestAxis] = flForce * flDepthRatio * iPushDir;
220+
} else {
221+
vecForce[iClosestAxis] = flForce * iPushDir;
222+
223+
if (iFlags & APS_Flag_AddForceInfluenceMode) {
224+
iFlags &= ~APS_Flag_AddForce;
225+
}
226+
}
227+
228+
@Base_Push(this, vecForce, iFlags);
229+
}

0 commit comments

Comments
 (0)