forked from UNLOZE/sm-plugins
vscripts: update to latest versions
This commit is contained in:
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
**
|
||||
*/
|
||||
#if defined _AESTHETIC_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _AESTHETIC_included
|
||||
#include <basic>
|
||||
#include <vscripts>
|
||||
#define CELL_SIZE 128.0
|
||||
|
||||
methodmap Chess < Basic
|
||||
{
|
||||
public Chess(int greenStart, int greenEnd, int purpleStart, int purpleEnd)
|
||||
{
|
||||
Basic myclass = new Basic();
|
||||
myclass.SetFloat("fGreenX", 2.0);
|
||||
myclass.SetFloat("fGreenY", 6.0);
|
||||
myclass.SetFloat("fPurpleX", 4.0);
|
||||
myclass.SetFloat("fPurpleY", 1.0);
|
||||
myclass.SetInt("iGreenStart", greenStart);
|
||||
myclass.SetInt("iGreenEnd", greenEnd);
|
||||
myclass.SetInt("iPurpleStart", purpleStart);
|
||||
myclass.SetInt("iPurpleEnd", purpleEnd);
|
||||
myclass.SetBool("bDead", false);
|
||||
return view_as<Chess>(myclass);
|
||||
}
|
||||
|
||||
property bool bDead
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetBool("bDead");
|
||||
}
|
||||
public set(bool val)
|
||||
{
|
||||
this.SetBool("bDead", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float greenX
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fGreenX");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fGreenX", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float greenY
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fGreenY");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fGreenY", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float purpleX
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fPurpleX");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fPurpleX", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float purpleY
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fPurpleY");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fPurpleY", val);
|
||||
}
|
||||
}
|
||||
|
||||
property int greenStart
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iGreenStart");
|
||||
}
|
||||
}
|
||||
|
||||
property int greenEnd
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iGreenEnd");
|
||||
}
|
||||
}
|
||||
|
||||
property int purpleStart
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iPurpleStart");
|
||||
}
|
||||
}
|
||||
|
||||
property int purpleEnd
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iPurpleEnd");
|
||||
}
|
||||
}
|
||||
|
||||
public bool Check(float x, float y)
|
||||
{
|
||||
return (-1.0 < x && x < 8.0 && -1.0 < y && y < 8.0 && !((x == this.greenX && y == this.greenY) || (x == this.purpleX && y == this.purpleY)));
|
||||
}
|
||||
|
||||
public void UpdateGreen(float dx, float dy)
|
||||
{
|
||||
this.greenX += dx;
|
||||
this.greenY += dy;
|
||||
}
|
||||
|
||||
public void UpdateGreenEnd(float dx, float dy)
|
||||
{
|
||||
float currentPos[3];
|
||||
GetOrigin(this.greenEnd, currentPos);
|
||||
float moveVector[3] = { 0.0, ... };
|
||||
moveVector[0] = dx * CELL_SIZE;
|
||||
moveVector[1] = dy * CELL_SIZE;
|
||||
float tmp[3];
|
||||
AddVectors(currentPos, moveVector, tmp);
|
||||
SetOrigin(this.greenEnd, tmp);
|
||||
}
|
||||
|
||||
public void MoveGreen(float dx, float dy)
|
||||
{
|
||||
if (this.Check(this.greenX + dx, this.greenY + dy))
|
||||
{
|
||||
this.UpdateGreen(dx, dy);
|
||||
this.UpdateGreenEnd(dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveStartToEnd(int start, int end)
|
||||
{
|
||||
float e_Orig[3];
|
||||
GetOrigin(end, e_Orig);
|
||||
SetOrigin(start, e_Orig);
|
||||
}
|
||||
|
||||
public void UpdatePurple(float dx, float dy)
|
||||
{
|
||||
this.purpleX += dx;
|
||||
this.purpleY += dy;
|
||||
}
|
||||
|
||||
public void UpdatePurpleEnd(float dx, float dy)
|
||||
{
|
||||
float currentPos[3];
|
||||
GetOrigin(this.purpleEnd, currentPos);
|
||||
float moveVector[3] = { 0.0, ... };
|
||||
moveVector[0] = dx * CELL_SIZE;
|
||||
moveVector[1] = dy * CELL_SIZE;
|
||||
float tmp[3];
|
||||
AddVectors(currentPos, moveVector, tmp);
|
||||
SetOrigin(this.purpleEnd, tmp);
|
||||
}
|
||||
|
||||
public void MovePurple(float dx, float dy)
|
||||
{
|
||||
if (this.Check(this.purpleX + dx, this.purpleY + dy))
|
||||
{
|
||||
this.UpdatePurple(dx, dy);
|
||||
this.UpdatePurpleEnd(dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckInLove()
|
||||
{
|
||||
if(this.bDead)
|
||||
return;
|
||||
float dx = this.greenX - this.purpleX;
|
||||
float dy = this.greenY - this.purpleY;
|
||||
if (dx < 0.0) dx *= -1.0;
|
||||
if (dy < 0.0) dy *= -1.0;
|
||||
if (dx + dy == 1.0)
|
||||
{
|
||||
this.bDead = true;
|
||||
EntFire("TotalTrigger", "FireUser2", "", "0.0", -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int DEFAULT_RETARGET_TICKS = 200;
|
||||
const float DEFAULT_MAX_VEL = 16.0;
|
||||
const float DEFAULT_MAX_ACC = 0.1;
|
||||
const float DEFAULT_RANGE = 100000.0;
|
||||
const float DEFAULT_PER_FRAME_MAX_VEL_DELTA = 0.0003333; // 2.0 / (120.0 * 50.0);
|
||||
const float DEFAULT_PER_FRAME_MAX_ACC_DELTA = 0.0000125; // 0.075 / (120.0 * 50.0);
|
||||
#define PI 3.14159
|
||||
|
||||
public bool SphereCollideWithWorld(const float[3] orig, const float radius, float degree, float[3] buffer, int entity)
|
||||
{
|
||||
|
||||
float inc = PI / degree;
|
||||
float phiStop = PI - inc;
|
||||
|
||||
float minDist = 1.0;
|
||||
for (float phi = 0.0; phi < PI; phi += inc)
|
||||
{
|
||||
// Avoid computing the full circle on the edge cases
|
||||
float theta = 0.0;
|
||||
if (phi == 0.0 || phi == phiStop)
|
||||
theta = PI - inc;
|
||||
|
||||
float cp = Cosine(phi);
|
||||
float sp = Sine(phi);
|
||||
for (; theta < 2 * PI; theta += inc)
|
||||
{
|
||||
float ct = Cosine(theta);
|
||||
float st = Sine(theta);
|
||||
float vec[3];
|
||||
vec[0] = ct * sp;
|
||||
vec[1] = st * sp;
|
||||
vec[2] = cp;
|
||||
ScaleVector(vec, radius);
|
||||
|
||||
float end[3];
|
||||
AddVectors(orig, vec, end);
|
||||
float dist = TraceLine(orig, end, entity);
|
||||
if ( 0 < dist && dist < minDist)
|
||||
{
|
||||
ScaleVector(vec, dist);
|
||||
AddVectors(orig, vec, buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
methodmap Eye < Basic
|
||||
{
|
||||
public Eye(int entity)
|
||||
{
|
||||
Basic myclass = new Basic();
|
||||
myclass.SetInt("iEntity", entity);
|
||||
myclass.SetInt("iTarget", -1);
|
||||
myclass.SetFloat("fBossRadius", 72.0);
|
||||
myclass.SetInt("iBossTeamTarget", 3);
|
||||
myclass.SetInt("iRetargetTicks", 0);
|
||||
myclass.SetFloat("fMaxVel", DEFAULT_MAX_VEL);
|
||||
myclass.SetFloat("fMaxAcc", DEFAULT_MAX_ACC);
|
||||
myclass.SetVector("vVec", { 0.0, 0.0, 0.0 } );
|
||||
myclass.SetVector("vAcc", { 0.0, 0.0, 0.0 } );
|
||||
myclass.SetFloat("fSavedVel", 0.0);
|
||||
myclass.SetFloat("fSavedAcc", 0.0);
|
||||
return view_as<Eye>(myclass);
|
||||
}
|
||||
|
||||
property int entity
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iEntity");
|
||||
}
|
||||
}
|
||||
|
||||
property int target
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iTarget");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iTarget", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float bossRadius
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fBossRadius");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fBossRadius", val);
|
||||
}
|
||||
}
|
||||
|
||||
property int bossTeamTarget
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iBossTeamTarget");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iBossTeamTarget", val);
|
||||
}
|
||||
}
|
||||
|
||||
property int retargetTicks
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iRetargetTicks");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iRetargetTicks", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float maxVel
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fMaxVel");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fMaxVel", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float maxAcc
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fMaxAcc");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fMaxAcc", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float savedVel
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fSavedVel");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fSavedVel", val);
|
||||
}
|
||||
}
|
||||
|
||||
property float savedAcc
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fSavedAcc");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fSavedAcc", val);
|
||||
}
|
||||
}
|
||||
|
||||
public void GetVel(float[3] vel)
|
||||
{
|
||||
this.GetVector("vVel", vel);
|
||||
}
|
||||
|
||||
public void SetVel(const float[3] vel)
|
||||
{
|
||||
this.SetVector("vVel", vel);
|
||||
}
|
||||
|
||||
public void GetAcc(float[3] acc)
|
||||
{
|
||||
this.GetVector("vAcc", acc);
|
||||
}
|
||||
|
||||
public void SetAcc(const float[3] acc)
|
||||
{
|
||||
this.SetVector("vAcc", acc);
|
||||
}
|
||||
|
||||
public void Retarget()
|
||||
{
|
||||
|
||||
// Start the gig
|
||||
this.retargetTicks = 0;
|
||||
int tempPlayer = -1;
|
||||
int currentPlayer = -1;
|
||||
int checkedPlayers = 0;
|
||||
float distance = DEFAULT_RANGE;
|
||||
|
||||
// While there is no target or
|
||||
// players found as potential targets aren't humans
|
||||
while (checkedPlayers < MaxClients) {
|
||||
currentPlayer = FindEntityByClassname(currentPlayer, "player");
|
||||
|
||||
// Only humans are valid
|
||||
if(currentPlayer != -1 &&
|
||||
IsPlayerAlive(currentPlayer) &&
|
||||
GetClientTeam(currentPlayer) == this.bossTeamTarget)
|
||||
{
|
||||
float tmp[3], s_orig[3], p_orig[3];
|
||||
GetOrigin(this.entity, s_orig);
|
||||
GetOrigin(currentPlayer, p_orig);
|
||||
SubtractVectors(s_orig, p_orig, tmp);
|
||||
float length = GetVectorLength(tmp);
|
||||
|
||||
// Make sure we're close enough
|
||||
if (length < distance)
|
||||
{
|
||||
tempPlayer = currentPlayer;
|
||||
distance = length;
|
||||
}
|
||||
}
|
||||
// Make sure we don't stay here forever
|
||||
checkedPlayers++;
|
||||
}
|
||||
|
||||
// Try the last bet if no player was found
|
||||
this.target = tempPlayer;
|
||||
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// Save the values
|
||||
this.savedVel = this.maxVel;
|
||||
this.savedAcc = this.maxAcc;
|
||||
|
||||
// Block movement (with a bit of velocity to avoid spinning)
|
||||
this.maxVel = 0.01;
|
||||
this.maxAcc = 0.0001;
|
||||
}
|
||||
|
||||
public void AllowMovement()
|
||||
{
|
||||
// Set either default or saved vals
|
||||
if (this.savedVel == 0.0) this.maxVel = DEFAULT_MAX_VEL;
|
||||
else this.maxVel = this.savedVel;
|
||||
|
||||
if (this.savedAcc == 0.0) this.maxAcc = DEFAULT_MAX_ACC;
|
||||
else this.maxAcc = this.savedAcc;
|
||||
|
||||
// Reset saved values
|
||||
this.savedVel = 0.0;
|
||||
this.savedAcc = 0.0;
|
||||
}
|
||||
|
||||
public void FakePhysicsMovement()
|
||||
{
|
||||
|
||||
// Get the center and end point
|
||||
float cnt[3];
|
||||
GetOrigin(this.entity, cnt);
|
||||
|
||||
// Make the boss face the target
|
||||
float tmp[3];
|
||||
this.GetVel(tmp);
|
||||
SetForwardVector(this.entity, tmp);
|
||||
|
||||
// If there is an impact, bounce
|
||||
float collPoint[3];
|
||||
if (SphereCollideWithWorld(cnt, this.bossRadius, 5.0, collPoint, this.entity))
|
||||
{
|
||||
|
||||
float vec[3];
|
||||
SubtractVectors(cnt, collPoint, vec);
|
||||
float norm[3], norm_copy[3];
|
||||
NormalizeVector(vec, norm);
|
||||
norm_copy[0] = norm[0];
|
||||
norm_copy[1] = norm[1];
|
||||
norm_copy[2] = norm[2];
|
||||
// Reflect velocity in a hacky way (not plane-accurate)
|
||||
float nn[3];
|
||||
NormalizeVector(norm, nn);
|
||||
this.GetVel(tmp);
|
||||
float dot = GetVectorDotProduct(tmp, nn);
|
||||
ScaleVector(norm_copy, 2 * dot);
|
||||
SubtractVectors(tmp, norm_copy, tmp);
|
||||
this.SetVel(tmp);
|
||||
EntFireByIndex(this.entity, "FireUser1", "", "0.0", this.target);
|
||||
// Move as far as we can
|
||||
ScaleVector(norm, this.bossRadius);
|
||||
AddVectors(cnt, norm, tmp);
|
||||
SetOrigin(this.entity, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
this.GetVel(tmp);
|
||||
AddVectors(cnt, tmp, tmp);
|
||||
SetOrigin(this.entity, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
public void Move()
|
||||
{
|
||||
|
||||
// If there is no target or the target is gone/dead, retarget
|
||||
if (this.target == -1 ||
|
||||
!IsValidEntity(this.target) ||
|
||||
!IsPlayerAlive(this.target) ||
|
||||
this.retargetTicks++ >= DEFAULT_RETARGET_TICKS) this.Retarget();
|
||||
|
||||
// Perform the update with the data from the previous moment
|
||||
float vel[3], tmp[3], acc[3];
|
||||
this.GetVel(vel);
|
||||
this.GetAcc(acc);
|
||||
AddVectors(vel, acc, tmp);
|
||||
this.SetVel(tmp);
|
||||
float length = GetVectorLength(tmp);
|
||||
if (length > this.maxVel)
|
||||
{
|
||||
ScaleVector(tmp, this.maxVel / length);
|
||||
this.SetVel(tmp);
|
||||
}
|
||||
this.SetAcc( { 0.0, 0.0, 0.0 } );
|
||||
|
||||
// Apply the higher accuracy movement deltas
|
||||
this.maxVel += DEFAULT_PER_FRAME_MAX_VEL_DELTA;
|
||||
this.maxAcc += DEFAULT_PER_FRAME_MAX_ACC_DELTA;
|
||||
|
||||
// Try to move, finally
|
||||
this.FakePhysicsMovement();
|
||||
|
||||
// Keep going if no target's there still
|
||||
if (this.target == -1) return;
|
||||
|
||||
// Try moving towards our target if it exists, otherwise don't
|
||||
|
||||
float tgtPos[3];
|
||||
GetOrigin(this.target, tgtPos);
|
||||
float bssPos[3];
|
||||
GetOrigin(this.entity, bssPos);
|
||||
float dir[3];
|
||||
SubtractVectors(tgtPos, bssPos, dir);
|
||||
|
||||
// Compute the length for later and normalize it if needed
|
||||
|
||||
length = GetVectorLength(dir);
|
||||
if (length > this.maxVel)
|
||||
ScaleVector(dir, this.maxVel / length);
|
||||
|
||||
// Compute the acceleration
|
||||
|
||||
this.GetVel(vel);
|
||||
SubtractVectors(dir, vel, acc);
|
||||
length = GetVectorLength(acc);
|
||||
if (length > this.maxAcc)
|
||||
{
|
||||
ScaleVector(acc, this.maxAcc / length);
|
||||
this.SetAcc(acc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,245 @@
|
||||
#if defined _JJBA_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _JJBA_included
|
||||
#include <basic>
|
||||
#include <vscripts>
|
||||
#include <float>
|
||||
|
||||
#define TICKRATE 0.1
|
||||
#define TARGET_DISTANCE 5000.0
|
||||
#define RETARGET_TIME 7.5
|
||||
#define SPEED_FORWARD 1.0
|
||||
#define SPEED_TURNING 0.5
|
||||
|
||||
stock float FloatMod(float num, float denom)
|
||||
{
|
||||
return num - denom * RoundToFloor(num / denom);
|
||||
}
|
||||
|
||||
stock float operator%(float oper1, float oper2)
|
||||
{
|
||||
return FloatMod(oper1, oper2);
|
||||
}
|
||||
|
||||
public bool IsValidPlayer(int player)
|
||||
{
|
||||
return player >= 1 && player <= 64 && IsValidEntity(player) && IsPlayerAlive(player);
|
||||
}
|
||||
|
||||
public float GetDistance(const float[3] v1, const float[3] v2)
|
||||
{
|
||||
return SquareRoot((v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1]) + (v1[2] - v2[2]) * (v1[2] - v2[2]));
|
||||
}
|
||||
|
||||
methodmap MovingNpc < Basic
|
||||
{
|
||||
public MovingNpc(int entity)
|
||||
{
|
||||
Basic myclass = new Basic();
|
||||
myclass.SetInt("iEntity", entity);
|
||||
myclass.SetInt("iTarget", -1);
|
||||
myclass.SetInt("iTf", -1);
|
||||
myclass.SetInt("iTs", -1);
|
||||
myclass.SetFloat("fTtime", 0.0);
|
||||
myclass.SetBool("bTicking", false);
|
||||
return view_as<MovingNpc>(myclass);
|
||||
}
|
||||
property int entity
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iEntity");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iEntity", val);
|
||||
}
|
||||
}
|
||||
property int target
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iTarget");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iTarget", val);
|
||||
}
|
||||
}
|
||||
property int tf
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iTf");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iTf", val);
|
||||
}
|
||||
}
|
||||
property int ts
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetInt("iTs");
|
||||
}
|
||||
public set(int val)
|
||||
{
|
||||
this.SetInt("iTs", val);
|
||||
}
|
||||
}
|
||||
property float ttime
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetFloat("fTtime");
|
||||
}
|
||||
public set(float val)
|
||||
{
|
||||
this.SetFloat("fTtime", val);
|
||||
}
|
||||
}
|
||||
property bool ticking
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return this.GetBool("bTicking");
|
||||
}
|
||||
public set(bool val)
|
||||
{
|
||||
this.SetBool("bTicking", val);
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
|
||||
if(!this.ticking)
|
||||
{
|
||||
this.ticking = true;
|
||||
CreateTimer(TICKRATE, Tick_Cb, this, TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if(this.ticking)
|
||||
{
|
||||
this.ticking = false;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetTargetYaw(const float[3] start, const float[3] target)
|
||||
{
|
||||
|
||||
float yaw = 0.00;
|
||||
float v[3];
|
||||
SubtractVectors(start, target, v);
|
||||
float vl = SquareRoot(v[0] * v[0] + v[1] * v[1]);
|
||||
yaw = 180.0 * ArcCosine(v[0] / vl) / 3.14159;
|
||||
if (v[1] < 0.0)
|
||||
yaw = -yaw;
|
||||
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public void SetThruster(bool fwd, int caller)
|
||||
{
|
||||
if(fwd)
|
||||
this.tf = caller;
|
||||
else
|
||||
this.ts = caller;
|
||||
}
|
||||
|
||||
public void SearchTarget()
|
||||
{
|
||||
|
||||
this.ttime = 0.00;
|
||||
this.target = -1;
|
||||
int h = -1;
|
||||
ArrayList candidates = new ArrayList();
|
||||
float orig[3];
|
||||
GetOrigin(this.entity, orig);
|
||||
while (-1 != (h = FindEntityByClassnameWithin(h, "player", orig, TARGET_DISTANCE)))
|
||||
{
|
||||
//check if target is a valid player + CT team(3) + health above 0 (not dead)
|
||||
if (GetClientTeam(h) == 3 && IsPlayerAlive(h))
|
||||
{
|
||||
//check if the target is in sight of the npc (this physbox origin+48 height)
|
||||
float t_orig[3];
|
||||
GetOrigin(this.entity, orig);
|
||||
orig[2] += 40.0;
|
||||
GetOrigin(h, t_orig);
|
||||
t_orig[2] += 48.0;
|
||||
if (TraceLine(orig, t_orig, this.entity) == 1.00)
|
||||
candidates.Push(h); //if everything required is OK, add the target to the list of candidates
|
||||
}
|
||||
}
|
||||
if(candidates.Length == 0)
|
||||
{
|
||||
delete candidates;
|
||||
return;
|
||||
}
|
||||
this.target = candidates.Get(GetRandomInt(0, candidates.Length - 1));
|
||||
|
||||
delete candidates;
|
||||
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
|
||||
EntFireByIndex(this.tf, "Deactivate", "", "0.00", -1);
|
||||
EntFireByIndex(this.ts, "Deactivate", "", "0.00", -1);
|
||||
if (!IsValidPlayer(this.target) || GetClientTeam(this.target) != 3 || this.ttime >= RETARGET_TIME)
|
||||
{
|
||||
this.SearchTarget();
|
||||
}
|
||||
this.ttime+=TICKRATE;
|
||||
EntFireByIndex(this.tf, "Activate", "", "0.02", -1);
|
||||
EntFireByIndex(this.ts, "Activate", "", "0.02", -1);
|
||||
float angl[3], s_orig[3], t_orig[3];
|
||||
GetAngles(this.entity, angl);
|
||||
float sa = angl[1];
|
||||
GetOrigin(this.entity, s_orig);
|
||||
GetOrigin(this.target, t_orig);
|
||||
float ta = this.GetTargetYaw(s_orig, t_orig);
|
||||
float ang = FloatAbs((sa - ta + 360.0) % 360.0);
|
||||
if (ang >= 180.0)
|
||||
EntFireByIndex(this.ts, "AddOutput", "angles 0 270 0", "0.00", -1);
|
||||
else
|
||||
EntFireByIndex(this.ts, "AddOutput", "angles 0 90 0", "0.00", -1);
|
||||
float angdif = (sa - ta - 180.0);
|
||||
while (angdif > 360.0) { angdif -= 180.0; }
|
||||
while (angdif < -180.0) { angdif += 360.0; }
|
||||
angdif = FloatAbs(angdif);
|
||||
GetOrigin(this.entity, s_orig);
|
||||
GetOrigin(this.target, t_orig);
|
||||
//float tdist = GetDistance(s_orig, t_orig);
|
||||
//float tdistz = (t_orig[2] - s_orig[2]);
|
||||
char input[128];
|
||||
Format(input, sizeof(input), "force %.4f", 3000.0 * SPEED_FORWARD);
|
||||
EntFireByIndex(this.tf, "AddOutput", input, "0.00", -1);
|
||||
Format(input, sizeof(input), "force %.4f", (3.0 * SPEED_TURNING) * angdif);
|
||||
EntFireByIndex(this.ts, "AddOutput", input, "0.00", -1);
|
||||
CreateTimer(TICKRATE, Tick_Cb, this, TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Tick_Cb(Handle timer, MovingNpc npc)
|
||||
{
|
||||
KillTimer(timer);
|
||||
if(npc.ticking)
|
||||
{
|
||||
|
||||
npc.Tick();
|
||||
}
|
||||
else
|
||||
{
|
||||
EntFireByIndex(npc.tf, "Deactivate", "", "0.00", -1);
|
||||
EntFireByIndex(npc.ts, "Deactivate", "", "0.00", -1);
|
||||
delete npc;
|
||||
}
|
||||
return Plugin_Stop;
|
||||
}
|
||||
Reference in New Issue
Block a user