Trước Khi Đọc.
Hướng dẫn này được thực hiện đặc biệt dành cho scripters mà biết làm thế nào để làm việc với vectơ.
Tôi sẽ cố gắng giải thích các mã càng nhiều càng tốt để mà ngay cả người dùng biết một chút ít về họ sẽ có thể hiểu!
Này "làm thế nào để" đã được thực hiện đặc biệt cho những người muốn thực hiện điều này trong các plugin của họ.
Lưu ý: Đây là một phương pháp rất hiệu quả, vấn đề duy nhất là có những tình huống hiếm hoi khi bạn không nhìn thấy một cầu thủ. Nhưng điều đó sẽ không là một vấn đề.
Lưu ý: Hướng dẫn này áp dụng đối với CS nhưng có thể được thực hiện trong mods khác! Tất cả những gì bạn cần làm là chỉ cần thay đổi các hằng số để phù hợp của bạn!
Mã và mô tả:
Trước hết chúng ta cần một số hằng số:
- Đầu tiên chúng ta cần định nghĩa một số hằng số đó sẽ có ích!
Đây là những cái mà cần phải được sửa đổi nếu bạn không hài lòng bởi kết quả mà bạn đang nhận được!
PHP Code:
#define GENERAL_X_Y_SORROUNDING 18.5 // 16.0
#define CONSTANT_Z_CROUCH_UP 31.25 // 32.0
#define CONSTANT_Z_CROUCH_DOWN 17.5 // 16.0
#define CONSTANT_Z_STANDUP_UP 34.0 // 36.0
#define CONSTANT_Z_STANDUP_DOWN 35.25 // 36.0
#define GENERAL_X_Y_SORROUNDING_HALF 9.25 // 8.0
#define GENERAL_X_Y_SORROUNDING_HALF2 12.0 // 8.0
#define CONSTANT_Z_CROUCH_UP_HALF 15.5 // 16.0
#define CONSTANT_Z_CROUCH_DOWN_HALF 8.75 // 8.0
#define CONSTANT_Z_STANDUP_UP_HALF 17.0 // 18.0
#define CONSTANT_Z_STANDUP_DOWN_HALF 17.5 // 18.0
#define ANGLE_COS_HEIGHT_CHECK 0.7071 // cos(45 degrees)
- Bây giờ chúng ta cần một số mảng cung cấp các plugin thứ tự của các tính toán.
PHP Code:
// Cái này dùng để xác định weapon head point
new const Float:weapon_edge_point[CSW_P90+1] =
{
0.00, 35.5, 0.00, 42.0, 0.00, 35.5, 0.00, 37.0, 37.0, 0.00, 35.5, 35.5, 32.0, 41.0, 32.0, 36.0, 41.0, 35.5, 41.0, 32.0, 37.0, 35.5, 42.0, 41.0, 44.0, 0.00, 35.5, 37.0, 32.0, 0.00, 32.0 }// Điều này được sử dụng như một mảng nhân bên
new const Float:vec_multi_lateral[] =
{
GENERAL_X_Y_SORROUNDING,
-GENERAL_X_Y_SORROUNDING,
GENERAL_X_Y_SORROUNDING_HALF2,
-GENERAL_X_Y_SORROUNDING_HALF }// This is used as height multiplicator if the user crouches!
new const Float:vec_add_height_crouch[] =
{
CONSTANT_Z_CROUCH_UP,
-CONSTANT_Z_CROUCH_DOWN,
CONSTANT_Z_CROUCH_UP_HALF,
-CONSTANT_Z_CROUCH_DOWN_HALF }// This is used as height multiplicator if the user stands up!
new const Float:vec_add_height_standup[] =
{
CONSTANT_Z_STANDUP_UP,
-CONSTANT_Z_STANDUP_DOWN,
CONSTANT_Z_STANDUP_UP_HALF,
-CONSTANT_Z_STANDUP_DOWN_HALF }
- Một dấu vết xử lý để lưu các kết quả phần (đối với khả năng hiển thị điểm)
PHP Code:
new thldpublic plugin_init()
{
// We create it in plugin_init
thdl = create_tr2()
}
public plugin_end()
{
// We free it on plugin end
free_tr2(thdl)
}
- Chúng tôi cũng cần một danh sách mà chúng ta có thể lưu các loại thực thể nếu các thực thể của chúng tôi là trong suốt hay không!
Điều này là cần thiết khi kiểm tra plugin của chúng tôi cho khả năng hiển thị người chơi offen!
PHP Code:
// These bitsums allow 2048 entities storage. I think that it is enough :P.
new bs_array_transp[64]
// BitSum, This is equal to 64*32 bools (good for quick search)
new bs_array_solid[64]
// BitSum, This is equal to 64*32 bools (good for quick search)
PHP Code:
#define add_transparent_ent(%1) bs_array_transp[((%1 - 1) / 32)] |= (1<<((%1 - 1) % 32))
#define del_transparent_ent(%1) bs_array_transp[((%1 - 1) / 32)] &= ~(1<<((%1 - 1) % 32))
#define is_transparent_ent(%1) (bs_array_transp[((%1 - 1) / 32)] & (1<<((%1 - 1) % 32)))
#define add_solid_ent(%1) bs_array_solid[((%1 - 1) / 32)] |= (1<<((%1 - 1) % 32))
#define del_solid_ent(%1) bs_array_solid[((%1 - 1) / 32)] &= ~(1<<((%1 - 1) % 32))
#define is_solid_ent(%1) (bs_array_solid[((%1 - 1) / 32)] & (1<<((%1 - 1) % 32)))
- Các chức năng theo dõi
PHP Code:
// This function checks if a point is visible from start to point! It will ignore glass and players! Also it will ignore the ignore_ent! bool:is_point_visible(const Float:start[3], const Float:point[3], ignore_ent)
{
engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
static Float:fraction
get_tr2(thdl, TR_flFraction, fraction)
// We will return the fraction
// If 1.0 that means that we didn't hit anything
return (fraction == 1.0)
}// This function is the same as above but will also check if the entity that we hited can be seen through bool:is_point_visible_texture(const Float:start[3], const Float:point[3], ignore_ent)
{
engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
// We save also the entity
static ent
ent = get_tr2(thdl, TR_pHit)
static Float:fraction
get_tr2(thdl, TR_flFraction, fraction)
// If we hit something start the checks
if (fraction != 1.0 && ent > 0)
{
// That means that we didn't know what we hited
if (!is_transparent_ent(ent) && !is_solid_ent(ent))
{
static texture_name[2]
static Float:vec[3]
// These calculations are made for security measures
// TraceTexture function will crash the server if used on short distances
xs_vec_sub(point, start, vec)
xs_vec_mul_scalar(vec, (5000.0 / xs_vec_len(vec)), vec)
xs_vec_add(start, vec, vec)
engfunc(EngFunc_TraceTexture, ent, start, vec, texture_name, charsmax(texture_name))
// If texture_name begins with { that means that we have a trasnaparent texture,
// if yes we will retrace and add that entity to our list as a transparent!
// If not then we add id as solid so it will not be needed to do the checks again!
if (equal(texture_name, "{"))
{
add_transparent_ent(ent)
ignore_ent = ent
engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
get_tr2(thdl, TR_flFraction, fraction)
return (fraction == 1.0)
}
else
{
add_solid_ent(ent)
return (fraction == 1.0)
}
}
// This means that the entity is registered as solid or transparent so on with the checks
else
{
if (is_solid_ent(ent))
{
return (fraction == 1.0)
}
else
{
ignore_ent = ent
engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
get_tr2(thdl, TR_flFraction, fraction)
return (fraction == 1.0)
}
}
}
return (fraction == 1.0)
}
- Vector functions [taken from xs.inc]
PHP Code:
// This will add two vectors stock xs_vec_add(const Float:in1[], const Float:in2[], Float:out[])
{
out[0] = in1[0] + in2[0];
out[1] = in1[1] + in2[1];
out[2] = in1[2] + in2[2];
}// This will substract two vectors stock xs_vec_sub(const Float:in1[], const Float:in2[], Float:out[])
{
out[0] = in1[0] - in2[0];
out[1] = in1[1] - in2[1];
out[2] = in1[2] - in2[2];
}// This will multiply a vector with a scalar stock xs_vec_mul_scalar(const Float:vec[], Float:scalar, Float:out[])
{
out[0] = vec[0] * scalar;
out[1] = vec[1] * scalar;
out[2] = vec[2] * scalar;
}// This will return the vector length stock Float:xs_vec_len(const Float:vec[3])
{
return floatsqroot(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
}// This will make a scalar multiplication between two vectors stock Float:xs_vec_dot(const Float:vec[], const Float:vec2[])
{
return (vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2])
}// This will check whether two vectors are equal bool:xs_vec_equal(const Float:vec1[], const Float:vec2[])
{
return (vec1[0] == vec2[0]) && (vec1[1] == vec2[1]) && (vec1[2] == vec2[2]);
}
PHP Code:
public plugin_precache()
{
register_forward(FM_Spawn, "fw_spawn", 1)
}
public fw_spawn(ent)
{
if (!pev_valid(ent))
return FMRES_IGNORED
static rendermode, Float:renderamt
rendermode = pev(ent, pev_rendermode)
pev(ent, pev_renderamt, renderamt)
// If transparent then add it to the list!
if (((rendermode == kRenderTransColor || rendermode == kRenderGlow || rendermode == kRenderTransTexture) && renderamt < 255.0) || (rendermode == kRenderTransAdd))
{
add_transparent_ent(ent)
return FMRES_IGNORED
}
return FMRES_IGNORED }
PHP Code:
stock is_player_visible(visor, target)
{
// Declarations, bla bla
static Float:origin[3], Float:start[3], Float:end[3], Float:addict[3], Float:plane_vec[3], Float:normal[3], ignore_ent
// The ignore entity is our visor at first (if needed we will change it!
// This will be used in the point tests!
ignore_ent = visor
// First of all we check if the player is behind the visor or not
// We get the visor origin
pev(visor, pev_origin, origin)
// We get the view angles of the visor
pev(visor, pev_v_angle, normal)
// We turn the angle vector into a direction vector
angle_vector(normal, ANGLEVECTOR_FORWARD, normal)
// We get the targets origin, this will be used to deremine if it the player is behind us
pev(target, pev_origin, end)
// We substract the two vectors to obtain a directional vector!
xs_vec_sub(end, origin, plane_vec)
// We normalize the vector so that we will be able to obtain the real angle between the vectors
xs_vec_mul_scalar(plane_vec, (1.0/xs_vec_len(plane_vec)), plane_vec)
// When we multiply two vectors that are normalized (their length is 1)
// We will obtain the cosinus of the angle between them, if this is negative then that means that the player is behind, so we return false!
if (xs_vec_dot(plane_vec, normal) < 0)
{
return false
}
// We get the view offsets and we add them to the origin to obtain the eye origin
pev(visor, pev_view_ofs, start)
xs_vec_add(start, origin, start)
// Origin becomes end
origin = end
// Until now we have 2 important vectors
// start - that is the eye origin of the visor
// origin - that is the target origin (usefull later)
// This is used only once to update the ignore_ent
// If point is visible then guess what, returning true!
if (is_point_visible_texture(start, origin, ignore_ent))
return true
// This will get the view offsets of the target, we will add them to obtain the eye origin
pev(target, pev_view_ofs, end)
xs_vec_add(end, origin, end)
// If eye origin is visible return true!
if (is_point_visible(start, end, ignore_ent))
return true
// Check weapon point, first we need to check if it is no equal to 0
if (weapon_edge_point[get_user_weapon(target)] != 0.00)
{
// We get the view angles and turn them in directional vectors
pev(target, pev_v_angle, addict)
angle_vector(addict, ANGLEVECTOR_FORWARD, addict)
// We multiply it to obtain the weapon headpoint
xs_vec_mul_scalar(addict, weapon_edge_point[get_user_weapon(target)], addict)
// We add it to the end origin to obtain the weapon headpoint
xs_vec_add(end, addict, end)
// If weapon head is visible true!
if (is_point_visible(start, end, ignore_ent))
return true
}
// We subtract them to obtain o directional vector that will be used in plane calculations!
xs_vec_sub(start, origin, normal)
// We have now an extra important vector
// normal - a directional vector between the start vector and the target origin
// This is the moment when we move on to plane checks
// These functions will create a plane that will rotate based on player position
// The checks will be done on points that will exist on this plane!
// First of all we normalize the normal vector
// This will be important when we have height problems.
xs_vec_mul_scalar(normal, 1.0/(xs_vec_len(normal)), normal)
// We turn the vector into an angle vector
vector_to_angle(normal, plane_vec)
// This will create a vector that will be orthogonal/perpendicular with the normal vector!
// This must be done to easily create the plane!
angle_vector(plane_vec, ANGLEVECTOR_RIGHT, plane_vec)
// This will check if we are almost at the same level with the target
if (floatabs(normal[2]) <= ANGLE_COS_HEIGHT_CHECK)
{
// We check whether the target crouches
// This is important to determine what multiplicator vector to use!
// This will create the plane
if (pev(target, pev_flags) & FL_DUCKING)
{
for (new i=0;i<4;i++)
{
if (i<2)
{
for (new j=0;j<2;j++)
{
// We multiply the directional vector and add it to the origin after that we check if it is visible
// The same happens in the other places so this one will be the only one that will be commented!
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_crouch[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
else
{
for (new j=2;j<4;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_crouch[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
}
}
else
{
for (new i=0;i<4;i++)
{
if (i<2)
{
for (new j=0;j<2;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_standup[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
else
{
for (new j=2;j<4;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_standup[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
}
}
}
else
{
// This is the same as the one above
// The only difference is that it also uses normal vector to move the points in front and in behind!
// Here is checked if you are above the player
if (normal[2] > 0.0)
{
normal[2] = 0.0
xs_vec_mul_scalar(normal, 1/(xs_vec_len(normal)), normal)
if (pev(target, pev_flags) & FL_DUCKING)
{
for (new i=0;i<4;i++)
{
if (i<2)
{
for (new j=0;j<2;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_crouch[j]
xs_vec_add(origin, addict, end)
xs_vec_mul_scalar(normal, (j == 0) ? (-GENERAL_X_Y_SORROUNDING) : (GENERAL_X_Y_SORROUNDING), addict)
xs_vec_add(end, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
else
{
for (new j=2;j<4;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_crouch[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
}
}
else
{
for (new i=0;i<4;i++)
{
if (i<2)
{
for (new j=0;j<2;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_standup[j]
xs_vec_add(origin, addict, end)
xs_vec_mul_scalar(normal, (j == 0) ? (-GENERAL_X_Y_SORROUNDING) : (GENERAL_X_Y_SORROUNDING), addict)
xs_vec_add(end, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
else
{
for (new j=2;j<4;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_standup[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
}
}
}
else
{
normal[2] = 0.0
xs_vec_mul_scalar(normal, 1/(xs_vec_len(normal)), normal)
if (pev(target, pev_flags) & FL_DUCKING)
{
for (new i=0;i<4;i++)
{
if (i<2)
{
for (new j=0;j<2;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_crouch[j]
xs_vec_add(origin, addict, end)
xs_vec_mul_scalar(normal, (j == 0) ? GENERAL_X_Y_SORROUNDING : (-GENERAL_X_Y_SORROUNDING), addict)
xs_vec_add(end, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
else
{
for (new j=2;j<4;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_crouch[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
}
}
else
{
for (new i=0;i<4;i++)
{
if (i<2)
{
for (new j=0;j<2;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_standup[j]
xs_vec_add(origin, addict, end)
xs_vec_mul_scalar(normal, (j == 0) ? GENERAL_X_Y_SORROUNDING : (-GENERAL_X_Y_SORROUNDING), addict)
xs_vec_add(end, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
else
{
for (new j=2;j<4;j++)
{
xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
addict[2] = vec_add_height_standup[j]
xs_vec_add(origin, addict, end)
if (is_point_visible(start, end, ignore_ent))
return true
}
}
}
}
}
}
// None visible?
return false }
Well you just need to do add this to the code in the plugin.
PHP Code:
stock spr_bombpublic plugin_precache()
{
spr_bomb = precache_model("sprites/ledglow.spr")
}stock bomb_led(const Float:point[3])
{
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_GLOWSPRITE)
engfunc(EngFunc_WriteCoord, point[0])
engfunc(EngFunc_WriteCoord, point[1])
engfunc(EngFunc_WriteCoord, point[2])
write_short(spr_bomb)
write_byte(1)
write_byte(3)
write_byte(255)
message_end()
}
PHP Code:
bool:is_point_visible(const Float:start[3], const Float:point[3], ignore_ent)
{
bomb_led(point)
return false }bool:is_point_visible_texture(const Float:start[3], const Float:point[3], ignore_ent)
{
bomb_led(point)
return false
0 nhận xét:
Post a Comment