HardOne
Member
- Joined
- Jan 15, 2006
- RedCents
- 61¢
Rich (BB code):
/*
MQ2MoveUtils plugin (2004.06.23) - tonio
- Updated 2005.06.05 by Quagmire
Currently contains two commands:
/stick -- /follow-like command, works for any pc/npc, default distance is melee range ("/stick help" for more options)
/circle -- autofaces character to run in a circle
"/stick" command by me
"/circle" command lifted from CyberTech's MQ2Twister plugin
*/
#include "../MQ2Plugin.h"
PreSetup("MQ2MoveUtils");
VOID CircleCommand(PSPAWNINFO pChar, PCHAR szLine);
float getRand(float n);
bool bCircling=FALSE;
bool bDrunken=false;
double CircleX=0.0f;
double CircleY=0.0f;
double CircleRadius=0.0f;
SYSTEMTIME stPrevCirc;
int millisDiff(SYSTEMTIME &stCurr, SYSTEMTIME &stPrev);
VOID StickCommand(PSPAWNINFO pChar, PCHAR szLine);
VOID DoUnstickBind(PCHAR Name, BOOL Down);
void ReleaseKeys();
void DoWalk(bool walk = false);
void DoFwd(bool hold, bool walk = false);
void DoBck(bool hold);
void DoLft(bool hold);
void DoRgt(bool hold);
void Load_INI(void);
bool IsBardClass(void);
void stickText();
void breakStick(bool stopMoving = true, bool quite = false);
float angularDistance(float h1, float h2);
bool MoveBindsLoaded=false;
bool stickOn=false;
bool setDist=false;
bool stickPaused=false;
bool stickHold=false;
bool moveBehind=false;
bool moveBehindOnce=false;
bool moveBack=false;
bool movePin=false;
bool casting=false;
bool mPause=false;
bool prevMoveBehind=false;
bool prevMovePin=false;
bool looseStick=false;
bool underwater=false;
bool stickhasmovedfwd=false;
short stickVerbosity=1;
short keysDown=0;
float stickDist=0.0;
float breakDist=250.0;
float currentDist=0.0;
float stickDistMod=0.0;
float stickDistModP=1.0;
PSPAWNINFO stickTarget;
eSpawnType stickTarget_Type;
SYSTEMTIME stPrevStick;
bool autoPauseEnabled=true;
bool breakDistEnabled=true;
bool breakOnWarpEnabled=true;
bool breakOnGateEnabled=true;
class MQ2StickType *pStickType = 0;
class MQ2StickType : public MQ2Type
{
public:
enum StickMembers {
Status=1,
Active=2,
Distance=3,
MoveBehind=4,
MovePause=5,
MoveBack=6,
Loose=7,
Paused=8,
Behind=9,
Stopped=10,
Pin=11,
};
MQ2StickType():MQ2Type("stick")
{
TypeMember(Status);
TypeMember(Active);
TypeMember(Distance);
TypeMember(MoveBehind);
TypeMember(MovePause);
TypeMember(MoveBack);
TypeMember(Loose);
TypeMember(Paused);
TypeMember(Behind);
TypeMember(Stopped);
TypeMember(Pin);
}
~MQ2StickType()
{
}
bool GetMember(MQ2VARPTR VarPtr, PCHAR Member, PCHAR Index, MQ2TYPEVAR &Dest)
{
PMQ2TYPEMEMBER pMember=MQ2StickType::FindMember(Member);
if (!pMember)
return false;
switch((StickMembers)pMember->ID)
{
case Status:
strcpy(DataTypeTemp,"OFF");
if( stickOn ) {
strcpy(DataTypeTemp,"ON");
}
if( stickPaused ) {
strcpy(DataTypeTemp,"PAUSED");
}
Dest.Ptr=DataTypeTemp;
Dest.Type=pStringType;
return true;
case Active:
Dest.DWord=stickOn;
Dest.Type=pBoolType;
return true;
case Distance:
Dest.Float=stickDist;
Dest.Type=pFloatType;
return true;
case MoveBehind:
Dest.DWord=moveBehind;
Dest.Type=pBoolType;
return true;
case MovePause:
Dest.DWord=mPause;
Dest.Type=pBoolType;
return true;
case MoveBack:
Dest.DWord=moveBack;
Dest.Type=pBoolType;
return true;
case Loose:
Dest.DWord=looseStick;
Dest.Type=pBoolType;
return true;
case Paused:
Dest.DWord=stickPaused;
Dest.Type=pBoolType;
return true;
case Behind:
if (ppTarget && pTarget) {
PSPAWNINFO psTarget = (PSPAWNINFO)pTarget;
PSPAWNINFO pChSpawn = (PSPAWNINFO) pCharSpawn;
Dest.DWord=(GetDistance(pChSpawn,psTarget) > stickDist || fabs(angularDistance(psTarget->Heading,pChSpawn->Heading)) > 45.0 )?false:true;
} else
Dest.DWord=false;
Dest.Type=pBoolType;
return true;
case Stopped:
if( ppTarget && pTarget ) {
PSPAWNINFO psTarget = stickHold?stickTarget:(PSPAWNINFO)pTarget;
PSPAWNINFO pChSpawn = (PSPAWNINFO) pCharSpawn;
Dest.DWord=(GetDistance(pChSpawn,psTarget)<=stickDist)?true:false;
} else
Dest.DWord=false;
Dest.Type=pBoolType;
return true;
case Pin:
Dest.DWord=movePin;
Dest.Type=pBoolType;
return true;
}
return false;
}
bool ToString(MQ2VARPTR VarPtr, PCHAR Destination)
{
strcpy(Destination,"OFF");
if( stickOn ) {
strcpy(Destination,"ON");
}
if( stickPaused ) {
strcpy(Destination,"PAUSED");
}
return true;
}
bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source)
{
return false;
}
bool FromString(MQ2VARPTR &VarPtr, PCHAR Source)
{
return false;
}
};
BOOL dataStick(PCHAR szName, MQ2TYPEVAR &Ret)
{
Ret.DWord=1;
Ret.Type=pStickType;
return true;
}
VOID CircleHelp()
{
WriteChatColor("Usage: /circle on|off|drunken <radius> [<y> <x>]",USERCOLOR_DEFAULT);
WriteChatColor(" Y and X are optional, if not specified will use your currect loc.",USERCOLOR_DEFAULT);
WriteChatColor(" Y and X are in the same order that /location prints them.",USERCOLOR_DEFAULT);
WriteChatColor(" If you call '/circle on <radius>' while not circling, it will start with your current loc and specified radius.",USERCOLOR_DEFAULT);
WriteChatColor(" If you call '/circle on <radius>' while already circling, it will update with your new loc and radius.",USERCOLOR_DEFAULT);
WriteChatColor(" If you call '/circle on' while already circling, it will update with your new loc using original radius.",USERCOLOR_DEFAULT);
}
VOID CircleCommand(PSPAWNINFO pChar, PCHAR szLine)
{
CHAR szTemp[MAX_STRING]={0};
CHAR szMsg[MAX_STRING]={0};
PSPAWNINFO pChSpawn = (PSPAWNINFO) pCharSpawn;
GetArg(szTemp,szLine,1);
if (!stricmp(szTemp,"help") || szLine[0]==0) {
CircleHelp();
return;
} else if (!stricmp(szTemp,"on") || !stricmp(szTemp,"drunken")) {
if( !stricmp(szTemp,"drunken") )
bDrunken=true;
else
bDrunken=false;
GetArg(szTemp,szLine,2);
if (!strlen(szTemp)) {
if (!bCircling) {
CircleHelp();
return;
} else if (!CircleRadius) {
// /circle on was called while we were already circling, but no radius was defined. oddddddd.
CircleHelp();
return;
}
} else {
CircleRadius = atof(szTemp);
}
GetArg(szTemp,szLine,3);
if (!strlen(szTemp)) {
CircleY = pChSpawn->Y + CircleRadius * sin(pChSpawn->Heading * PI / 256.0);
} else {
CircleY = atof(szTemp);
}
GetArg(szTemp,szLine,4);
if (!strlen(szTemp)) {
CircleX = pChSpawn->X - CircleRadius * cos(pChSpawn->Heading * PI / 256.0);
} else {
CircleX = atof(szTemp);
}
if (CircleRadius) bCircling = true;
sprintf(szMsg, "Circling Radius %g, center %g %g", CircleRadius, CircleY, CircleX);
WriteChatColor(szMsg, CONCOLOR_YELLOW);
} else {
if (!stricmp(szTemp,"off")) {
bCircling = false;
}
}
}
void StickHelp()
{
WriteChatColor("Usage: /stick [on|hold|off|pause|unpause|reload] [<dist>] [behind|behindonce|pin] [mpause] [moveback] [loose] [-<dist>] [<perc>%] [uw]");
WriteChatColor(" /stick - Sticks you within melee range of your target");
WriteChatColor(" /stick hold - Stores your current target, sticks to it even if you lose/change target");
WriteChatColor(" /stick off - Breaks off from stick (moving manually also breaks off from stick");
WriteChatColor(" /stick pause - Pauses following (can move normally while paused)");
WriteChatColor(" /stick unpause - Resumes following");
WriteChatColor(" /stick reload - Reload values from ini file");
WriteChatColor(" /stick <dist> - Sticks you within <dist> units of your target");
WriteChatColor(" /stick behind - Keeps you behind your target");
WriteChatColor(" /stick behindonce - Moves behind your target once");
WriteChatColor(" /stick pin - Keeps you to the side of your target");
WriteChatColor(" /stick mpause - Causes manual movement to pause stick instead of breaking it");
WriteChatColor(" /stick moveback - Moves character back to try to stay at exactly stick distance");
WriteChatColor(" /stick loose - Checks distance/angle less often, and turns slower, for a more human-controlled look");
WriteChatColor(" /stick uw - Looks up or down to track target, useful for underwater /stick");
WriteChatColor(" /stick -<dist> - Substracts <dist> from the stick distance");
WriteChatColor(" /stick <perc>% - Multiplies stick distance by <perc> percent");
}
VOID StickCommand(PSPAWNINFO pChar, PCHAR szLine)
{
char currentArg[MAX_STRING];
int argn=1;
GetArg(currentArg,szLine,argn++);
if( !strncmp(currentArg,"pause",6) ) {
ReleaseKeys();
stickPaused = true;
// GetArg(currentArg,szLine,argn++);
return;
} else if( !strncmp( currentArg,"unpause",8 ) ) {
stickPaused = false;
// GetArg(currentArg,szLine,argn++);
return;
}
if (!stickOn)
DoWalk(false);
ReleaseKeys();
stickOn=true;
stickPaused=false;
stickHold=false;
setDist=false;
moveBehind=false;
moveBehindOnce=false;
prevMoveBehind=false;
movePin=false;
prevMovePin=false;
moveBack=false;
mPause=false;
looseStick=false;
underwater=false;
stickhasmovedfwd=false;
stickTarget=NULL;
stickTarget_Type=NONE;
stickDistMod=0.0f;
stickDistModP=1.0f;
while( *currentArg ) {
if( !strncmp(currentArg,"on",3) ) {
stickOn = true;
} else if( strstr(currentArg,"%") ) {
stickDistModP = (float)atof(currentArg) / 100.0f;
if( setDist )
stickDist *= stickDistModP;
stickOn = true;
} else if( isdigit(currentArg[0]) || currentArg[0]=='.' ) {
setDist = true;
stickDist = (float)atof(currentArg) * stickDistModP + stickDistMod;
stickOn = true;
} else if( currentArg[0]=='-' ) {
stickDistMod = (float)atof(currentArg);
if( setDist )
stickDist += stickDistMod;
stickOn = true;
} else if( !strncmp(currentArg,"mpause",7) ) {
mPause = true;
stickOn = true;
} else if( !strncmp(currentArg,"moveback",9) ) {
moveBack = true;
stickOn = true;
} else if( !strncmp(currentArg,"loose",6) ) {
looseStick = true;
stickOn = true;
} else if( !strncmp(currentArg,"uw",3 ) ) {
underwater=true;
stickOn=true;
} else if( !strncmp(currentArg,"off",4) ) {
breakStick();
break;
} else if( !strncmp(currentArg,"hold",5) ) {
stickOn = true;
if( ppTarget && pTarget ) {
if (((PSPAWNINFO) pTarget)->SpawnID == ((PSPAWNINFO) pLocalPlayer)->SpawnID) {
WriteChatColor("You cannot stick hold to yourself.");
breakStick(true, true);
return;
}
stickHold = true;
stickTarget = (PSPAWNINFO)pTarget;
stickTarget_Type = stickTarget ? GetSpawnType(stickTarget) : NONE;
}
} else if( !strncmp(currentArg,"behind",7) ) {
stickOn=true;
moveBehind=true;
moveBehindOnce=false;
movePin=false;
} else if( !strncmp(currentArg,"behindonce",11) ) {
stickOn=true;
moveBehindOnce=true;
moveBehind=false;
movePin=false;
} else if( !strncmp(currentArg,"pin",3) ) {
stickOn=true;
movePin=true;
moveBehind=false;
moveBehindOnce=false;
} else if( !strncmp(currentArg,"reload",7) ) {
breakStick();
Load_INI();
WriteChatColor("Ini file reloaded.");
break;
} else {
breakStick();
StickHelp();
break;
}
GetArg(currentArg,szLine,argn++);
}
if( stickOn ) {
stickHold = stickHold && stickTarget && stickTarget->SpawnID;
if( (ppTarget && pTarget) || (stickHold && stickTarget && stickTarget->SpawnID) ) {
if( FindSpeed((PSPAWNINFO)pCharSpawn) < 0 ) {
DoFwd(false);
}
currentDist=GetDistance((PSPAWNINFO)pCharSpawn,stickHold?stickTarget:((PSPAWNINFO)pTarget));
}
stickText();
}
}
VOID DoUnstickBind(PCHAR Name, BOOL Down)
{
if( ! Down ) {
keysDown--;
if( keysDown == 0 && mPause ) {
stickPaused = false;
moveBehind = prevMoveBehind;
movePin = prevMovePin;
}
} else {
keysDown++;
if(!stickPaused && stickOn ) {
if( mPause && strncmp(Name,"UNSTICK_STRAFE_RGT",12) && strncmp(Name,"UNSTICK_STRAFE_LFT",19) ) {
stickPaused = true;
} else if( !strncmp(Name,"UNSTICK_STRAFE_RGT",12) || !strncmp(Name,"UNSTICK_STRAFE_LFT",19) ) {
if( mPause ) {
prevMoveBehind = moveBehind || prevMoveBehind;
prevMovePin = movePin || prevMovePin;
moveBehind = false;
} else {
prevMoveBehind = moveBehind = false;
prevMovePin = movePin = false;
}
} else {
breakStick((strncmp(Name,"UNSTICK_BCK",12) && strncmp(Name,"UNSTICK_FWD",12)));
}
}
}
}
VOID HandleCircle() {
static int counter = 0;
double distance;
double heading;
PSPAWNINFO pChSpawn = (PSPAWNINFO) pCharSpawn;
if (!GetCharInfo() || !bCircling) return;
double X = pChSpawn->X - CircleX;
double Y = pChSpawn->Y - CircleY;
distance = sqrt(X*X + Y*Y);
if (distance>(CircleRadius*(2.0/3.0))) {
heading=atan2(pChSpawn->Y - CircleY, CircleX - pChSpawn->X) * 180.0f / PI + 90.0f;
heading += 90.0f * (CircleRadius/distance);
heading *= 512.0f/360.0f;
if( heading >= 512.0f ) heading -= 512.0f;
if( heading < 0.0f ) heading += 512.0f;
if( bDrunken ) {
gFaceAngle = (float)heading;
} else {
pChSpawn->Heading = (float)heading;
}
}
}
float angularDistance(float h1, float h2)
{
if( h1 == h2 ) return 0.0;
if( fabs(h1-h2) > 256.0 )
*(h1<h2?&h1:&h2) += 512.0;
return (fabs(h1-h2)>256.0)?(h2-h1):(h1-h2);
}
void HandleStick()
{
if( (stickHold && (!stickTarget || !(stickTarget->SpawnID) || stickTarget_Type!=GetSpawnType(stickTarget))) || (!stickHold && ((!ppTarget) || (!pTarget))) ) {
breakStick();
return;
}
PSPAWNINFO psTarget = stickHold?stickTarget:(PSPAWNINFO)pTarget;
PSPAWNINFO pChSpawn = (PSPAWNINFO) pCharSpawn;
PSPAWNINFO pLPlayer = (PSPAWNINFO) pLocalPlayer;
if (!pChSpawn || !pChSpawn->pActorInfo || !psTarget || !pLPlayer || !pLPlayer->pCharInfo) {
WriteChatColor("Null pointer, breaking stick");
breakStick();
return;
}
float prevDist = currentDist;
if( !setDist )
stickDist = (psTarget->StandState?get_melee_range(pLocalPlayer,(EQPlayer *)psTarget):15.0f) * stickDistModP + stickDistMod;
currentDist=GetDistance(pChSpawn,psTarget);
if( breakOnWarpEnabled && (currentDist-prevDist) > breakDist ) {
breakStick();
return;
}
if ( ( ((long) (pChSpawn->pActorInfo->CastingSpellID)) >= 0 && !(IsBardClass()) ) || pChSpawn->StandState != STANDSTATE_STAND || pLPlayer->pCharInfo->Stunned==1 || psTarget->SpawnID == pChSpawn->SpawnID ) {
if( !casting ) {
casting = true;
ReleaseKeys();
}
} else if( casting ) {
casting = false;
}
if( (!stickPaused && !casting) || !autoPauseEnabled ) {
float newHeading = (float) (atan2(psTarget->X - pChSpawn->X, psTarget->Y - pChSpawn->Y) * 256.0 / PI);
if( newHeading >= 512.0f) newHeading -= 512.0f;
if( newHeading < 0.0f ) newHeading += 512.0f;
if (stickhasmovedfwd && fabs(pChSpawn->Heading - newHeading) >= 200 && currentDist < 10) {
DoBck(true);
return;
} else {
DoBck(false);
}
if( looseStick ) {
gFaceAngle = newHeading;
} else {
pChSpawn->Heading = newHeading;
}
//underwater = pChSpawn->pActorInfo->UnderWater==5;
if( underwater ) {
double lookAngle = atan2(psTarget->Z + psTarget->AvatarHeight*StateHeightMultiplier(psTarget->StandState) -
pChSpawn->Z - pChSpawn->AvatarHeight*StateHeightMultiplier(pChSpawn->StandState),
currentDist) * 256.0f / PI;
if ( looseStick ) {
gLookAngle = lookAngle;
} else {
pChSpawn->CameraAngle = (FLOAT)lookAngle;
}
}
if ( currentDist > (stickDist * 3) ) {
// too far away, dont do pin or behind
} else if( moveBehind || moveBehindOnce ) {
float angDist = angularDistance(psTarget->Heading,pChSpawn->Heading);
if( fabs(angDist) > 45.0 ) {
if(angDist < 0.0) {
// strafe left
DoLft(true);
} else {
// strage right
DoRgt(true);
}
} else {
moveBehindOnce = false;
DoLft(false);
DoRgt(false);
}
} else if (movePin) {
FLOAT angDist = angularDistance(psTarget->Heading,pChSpawn->Heading);
if((angDist > 0 && angDist <= 112) || angDist < -144) { //blahblah
DoLft(true);
} else if ((angDist < 0 && angDist > -112) || angDist > 144) {
DoRgt(true);
} else {
DoLft(false);
DoRgt(false);
}
}
if( currentDist > stickDist) {
// if distance is less than 10, walk
DoFwd(true, ((currentDist - stickDist) <= 10.0));
} else if( moveBack && currentDist < (stickDist-5.0) ) {
DoBck(true);
} else {
DoFwd(false);
DoBck(false);
}
}
}
void
Load_INI(VOID)
{
char szTemp[MAX_STRING], szTemp2[MAX_STRING];
// Defaults
GetPrivateProfileString("Defaults","AutoPause","on",szTemp,MAX_STRING,INIFileName);
autoPauseEnabled=(strncmp(szTemp,"on",3)==0);
sprintf(szTemp,"%s",autoPauseEnabled?"on":"off");
WritePrivateProfileString("Defaults","AutoPause",szTemp,INIFileName);
GetPrivateProfileString("Defaults","BreakOnWarp","on",szTemp,MAX_STRING,INIFileName);
breakOnWarpEnabled=(strncmp(szTemp,"on",3)==0);
sprintf(szTemp,"%s",breakOnWarpEnabled?"on":"off");
WritePrivateProfileString("Defaults","BreakOnWarp",szTemp,INIFileName);
GetPrivateProfileString("Defaults","BreakDist","250.0",szTemp,MAX_STRING,INIFileName);
breakDist = (float)atof(szTemp);
sprintf(szTemp,"%.1f",breakDist);
WritePrivateProfileString("Defaults","BreakDist",szTemp,INIFileName);
GetPrivateProfileString("Defaults","BreakOnGate","on",szTemp,MAX_STRING,INIFileName);
breakOnGateEnabled=(strncmp(szTemp,"on",3)==0);
sprintf(szTemp,"%s",breakOnGateEnabled?"on":"off");
WritePrivateProfileString("Defaults","BreakOnGate",szTemp,INIFileName);
stickVerbosity=(short)GetPrivateProfileInt("Defaults","Verbosity",1,INIFileName);
sprintf(szTemp,"%d",stickVerbosity);
WritePrivateProfileString("Defaults","Verbosity",szTemp,INIFileName);
// Character specific
GetPrivateProfileString(GetCharInfo()->Name,"AutoPause",autoPauseEnabled?"on":"off",szTemp,MAX_STRING,INIFileName);
autoPauseEnabled=(strncmp(szTemp,"on",3)==0);
GetPrivateProfileString(GetCharInfo()->Name,"BreakOnWarp",breakOnWarpEnabled?"on":"off",szTemp,MAX_STRING,INIFileName);
breakOnWarpEnabled=(strncmp(szTemp,"on",3)==0);
sprintf(szTemp2,"%.1f",breakDist);
GetPrivateProfileString(GetCharInfo()->Name,"BreakDist",szTemp2,szTemp,MAX_STRING,INIFileName);
breakDist = (float)atof(szTemp);
GetPrivateProfileString(GetCharInfo()->Name,"BreakOnGate",breakOnGateEnabled?"on":"off",szTemp,MAX_STRING,INIFileName);
breakOnGateEnabled=(strncmp(szTemp,"on",3)==0);
stickVerbosity=(short)GetPrivateProfileInt(GetCharInfo()->Name,"Verbosity",stickVerbosity,INIFileName);
}
bool IsBardClass()
{
if(strncmp(pEverQuest->GetClassDesc(GetCharInfo2()->Class),"Bard",5))
return false;
else
return true;
}
PLUGIN_API VOID OnPulse(VOID)
{
if (bCircling) {
if( bDrunken ) {
SYSTEMTIME stCurr;
GetSystemTime(&stCurr);
if( millisDiff(stCurr,stPrevCirc) > 900 + (int)getRand(600.0) ) {
GetSystemTime(&stPrevCirc);
HandleCircle();
}
} else {
HandleCircle();
}
}
if( stickOn ) {
if( looseStick ) {
SYSTEMTIME stCurr;
GetSystemTime(&stCurr);
if( millisDiff(stCurr,stPrevStick) > 100 + (int)getRand(200.0) ) {
GetSystemTime(&stPrevStick);
HandleStick();
}
} else {
HandleStick();
}
}
}
void ReleaseKeys() {
DoWalk(false);
DoFwd(false);
DoBck(false);
DoRgt(false);
DoLft(false);
}
void DoWalk(bool walk) {
bool state_walking = (*EQADDR_RUNWALKSTATE) ? false : true;
float SpeedModifier = *((float*) &(((PSPAWNINFO) pLocalPlayer)->pActorInfo->Unknown0x0af[25]));
// float SpeedModifier = ((PSPAWNINFO) pLocalPlayer)->pActorInfo->SpeedModifier;
if (SpeedModifier < 0)
walk = false; // we're snared, dont go into walk mode no matter what
if ( (walk && !state_walking) || (!walk && state_walking) ) {
MQ2Globals::ExecuteCmd(FindMappableCommand("run_walk"),1,0);
MQ2Globals::ExecuteCmd(FindMappableCommand("run_walk"),0,0);
}
}
void DoFwd(bool hold, bool walk) {
static bool held = false;
if ( hold ) {
stickhasmovedfwd = true;
DoWalk(walk);
DoBck(false);
if (!held)
MQ2Globals::ExecuteCmd(FindMappableCommand("forward"),1,0);
held = true;
} else {
DoWalk(false);
if (held)
MQ2Globals::ExecuteCmd(FindMappableCommand("forward"),0,0);
held = false;
}
}
void DoBck(bool hold) {
static bool held = false;
if( hold ) {
DoFwd(false);
if (!held)
MQ2Globals::ExecuteCmd(FindMappableCommand("back"),1,0);
held = true;
} else {
if (held)
MQ2Globals::ExecuteCmd(FindMappableCommand("back"),0,0);
held = false;
}
}
void DoLft(bool hold) {
static bool held = false;
if( hold ) {
DoRgt(false);
if (!held)
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_left"),1,0);
held = true;
} else {
if (held)
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_left"),0,0);
held = false;
}
}
void DoRgt(bool hold) {
static bool held = false;
if( hold ) {
DoLft(false);
if (!held)
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_right"),1,0);
held = true;
} else {
if (held)
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_right"),0,0);
held = false;
}
}
float getRand(float n)
{
return (n * rand() / (RAND_MAX+1.0f));
}
int millisDiff(SYSTEMTIME &stCurr, SYSTEMTIME &stPrev)
{
SYSTEMTIME stResult;
FILETIME ftPrev, ftCurr, ftResult;
ULARGE_INTEGER prev,curr,result;
GetSystemTime(&stCurr);
SystemTimeToFileTime(&stPrev,&ftPrev);
SystemTimeToFileTime(&stCurr,&ftCurr);
prev.HighPart = ftPrev.dwHighDateTime;
prev.LowPart = ftPrev.dwLowDateTime;
curr.HighPart = ftCurr.dwHighDateTime;
curr.LowPart = ftCurr.dwLowDateTime;
result.QuadPart = curr.QuadPart - prev.QuadPart;
ftResult.dwHighDateTime = result.HighPart;
ftResult.dwLowDateTime = result.LowPart;
FileTimeToSystemTime(&ftResult,&stResult);
return ((int)(stResult.wSecond * 1000 + stResult.wMilliseconds));
}
void stickText()
{
char szTemp[MAX_STRING];
if( stickVerbosity == 1 ) {
if( stickPaused ) {
WriteChatColor("Stick paused.");
} else if( stickOn ) {
if( stickHold ) {
sprintf(szTemp,"You are now sticking to %s.",stickTarget->DisplayedName);
} else if( ppTarget && pTarget ) {
sprintf(szTemp,"You are now sticking to %s.",((PSPAWNINFO)pTarget)->DisplayedName);
} else {
sprintf(szTemp,"Need a target for stick.");
}
WriteChatColor(szTemp);
} else {
WriteChatColor("You are no longer sticking to anything.");
}
}
}
void breakStick(bool stopMoving, bool quite)
{
stickOn=false;
stickPaused=false;
stickHold=false;
setDist=false;
moveBehind=false;
prevMoveBehind=false;
moveBehindOnce=false;
movePin=false;
prevMovePin=false;
moveBack=false;
mPause=false;
looseStick=false;
underwater=false;
stickTarget=NULL;
stickDistMod=0.0;
stickDistModP=1.0;
if( stopMoving )
ReleaseKeys();
else {
DoWalk(false);
DoLft(false);
DoRgt(false);
}
if (!quite)
stickText();
}
VOID CreateBinds(){
if (MoveBindsLoaded)
return;
MoveBindsLoaded=true;
AddMQ2KeyBind("UNSTICK_FWD",DoUnstickBind);
AddMQ2KeyBind("UNSTICK_BCK",DoUnstickBind);
AddMQ2KeyBind("UNSTICK_LFT",DoUnstickBind);
AddMQ2KeyBind("UNSTICK_RGT",DoUnstickBind);
AddMQ2KeyBind("UNSTICK_STRAFE_LFT",DoUnstickBind);
AddMQ2KeyBind("UNSTICK_STRAFE_RGT",DoUnstickBind);
SetMQ2KeyBind("UNSTICK_FWD",false,pKeypressHandler->NormalKey[FindMappableCommand("forward")]);
SetMQ2KeyBind("UNSTICK_FWD",true,pKeypressHandler->AltKey[FindMappableCommand("forward")]);
SetMQ2KeyBind("UNSTICK_BCK",false,pKeypressHandler->NormalKey[FindMappableCommand("back")]);
SetMQ2KeyBind("UNSTICK_BCK",true,pKeypressHandler->AltKey[FindMappableCommand("back")]);
SetMQ2KeyBind("UNSTICK_LFT",false,pKeypressHandler->NormalKey[FindMappableCommand("left")]);
SetMQ2KeyBind("UNSTICK_LFT",true,pKeypressHandler->AltKey[FindMappableCommand("left")]);
SetMQ2KeyBind("UNSTICK_RGT",false,pKeypressHandler->NormalKey[FindMappableCommand("right")]);
SetMQ2KeyBind("UNSTICK_RGT",true,pKeypressHandler->AltKey[FindMappableCommand("right")]);
SetMQ2KeyBind("UNSTICK_STRAFE_LFT",false,pKeypressHandler->NormalKey[FindMappableCommand("strafe_left")]);
SetMQ2KeyBind("UNSTICK_STRAFE_LFT",true,pKeypressHandler->AltKey[FindMappableCommand("strafe_left")]);
SetMQ2KeyBind("UNSTICK_STRAFE_RGT",false,pKeypressHandler->NormalKey[FindMappableCommand("strafe_right")]);
SetMQ2KeyBind("UNSTICK_STRAFE_RGT",true,pKeypressHandler->AltKey[FindMappableCommand("strafe_right")]);
}
VOID DestroyBinds()
{
if (!MoveBindsLoaded)
return;
RemoveMQ2KeyBind("UNSTICK_FWD");
RemoveMQ2KeyBind("UNSTICK_BCK");
RemoveMQ2KeyBind("UNSTICK_LFT");
RemoveMQ2KeyBind("UNSTICK_RGT");
RemoveMQ2KeyBind("UNSTICK_STRAFE_LFT");
RemoveMQ2KeyBind("UNSTICK_STRAFE_RGT");
}
// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
DebugSpewAlways("Initializing MQ2MoveUtils");
// Add commands, macro parameters, hooks, etc.
AddCommand("/circle",CircleCommand,0,1,1);
AddCommand("/stick",StickCommand);
AddMQ2Data("Stick",dataStick);
pStickType = new MQ2StickType;
srand((unsigned int)time(NULL));
if (gGameState==GAMESTATE_INGAME) {
CreateBinds();
}
GetSystemTime(&stPrevCirc);
GetSystemTime(&stPrevStick);
}
// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
DebugSpewAlways("Shutting down MQ2MoveUtils");
// Remove commands, macro parameters, hooks, etc.
RemoveMQ2Data("Stick");
RemoveCommand("/circle");
RemoveCommand("/stick");
delete pStickType;
DestroyBinds();
}
PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color)
{
if( breakOnGateEnabled && (stickHold?(stickTarget!=NULL):(ppTarget && pTarget)) ) {
char szTemp[MAX_STRING];
sprintf(szTemp,"%s Gates.",stickHold?stickTarget->DisplayedName:((PSPAWNINFO)pTarget)->DisplayedName);
if( ! strcmp(szTemp,Line) ) {
DoFwd(false);
stickOn = false;
}
}
return 0;
}
PLUGIN_API VOID SetGameState(DWORD GameState)
{
if (GameState==GAMESTATE_INGAME) {
CreateBinds();
Load_INI();
} else {
stickOn=false;
stickPaused=false;
stickHold=false;
setDist=false;
stickTarget=NULL;
bCircling=false;
}
}
// Called after entering a new zone
PLUGIN_API VOID OnZoned(VOID)
{
DoWalk(false);
}

