Moderator: MacroQuest Developers

Code: Select all
/*
MQ2MoveUtils plugin (2004.06.23) - tonio
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 DoFwd(bool hold);
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);
float StateHeightMultiplier(DWORD StandState);
bool MoveBindsLoaded=false;
bool stickOn=false;
bool setDist=false;
bool stickPaused=false;
bool stickHold=false;
bool moveBehind=false;
bool moveBack=false;
bool casting=false;
bool mPause=false;
bool prevMoveBehind=false;
bool looseStick=false;
bool underwater=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;
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
};
MQ2StickType():MQ2Type("stick")
{
TypeMember(Status);
TypeMember(Active);
TypeMember(Distance);
TypeMember(MoveBehind);
TypeMember(MovePause);
TypeMember(MoveBack);
TypeMember(Loose);
TypeMember(Paused);
}
~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;
}
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] [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 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) ) {
DoFwd(false);
stickPaused = true;
GetArg(currentArg,szLine,argn++);
return;
} else if( !strncmp( currentArg,"unpause",8 ) ) {
stickPaused = false;
GetArg(currentArg,szLine,argn++);
return;
}
stickOn=true;
stickPaused=false;
stickHold=false;
setDist=false;
moveBehind=false;
prevMoveBehind=false;
moveBack=false;
mPause=false;
looseStick=false;
underwater=false;
stickTarget=NULL;
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 ) {
stickHold = true;
stickTarget = (PSPAWNINFO)pTarget;
}
} else if( !strncmp(currentArg,"behind",7) ) {
stickOn=true;
moveBehind=true;
} else if( !strncmp(currentArg,"reload",7) ) {
breakStick();
Load_INI();
WriteChatColor("Ini file reloaded.");
break;
} else {
breakStick();
StickHelp();
break;
}
GetArg(currentArg,szLine,argn++);
}
if( stickOn ) {
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;
}
} 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;
moveBehind = false;
} else {
prevMoveBehind = moveBehind = 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))) || (!stickHold && ((!ppTarget) || (!pTarget))) ) {
breakStick();
} else {
PSPAWNINFO psTarget = stickHold?stickTarget:(PSPAWNINFO)pTarget;
PSPAWNINFO pChSpawn = (PSPAWNINFO) pCharSpawn;
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()) ) {
if( !casting ) {
casting = true;
DoFwd(false);
}
} 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( looseStick ) {
gFaceAngle = newHeading;
} else {
pChSpawn->Heading = newHeading;
}
//underwater = pChSpawn->pActorInfo->UnderWater==5;
if( underwater ) {
double Distance = DistanceToSpawn(pChSpawn,psTarget);
double lookAngle = atan2(psTarget->Z + psTarget->AvatarHeight*StateHeightMultiplier(psTarget->StandState) -
pChSpawn->Z - pChSpawn->AvatarHeight*StateHeightMultiplier(pChSpawn->StandState),
(FLOAT)Distance) * 256.0f / PI;
if ( looseStick ) {
gLookAngle = lookAngle;
} else {
pChSpawn->CameraAngle = (FLOAT)lookAngle;
}
}
if( moveBehind ) {
if( fabs(angularDistance(psTarget->Heading,pChSpawn->Heading)) > 45.0 ) {
if(angularDistance(psTarget->Heading,pChSpawn->Heading) < 0.0) {
// strafe left
DoLft(true);
} else {
// strage right
DoRgt(true);
}
} else {
DoLft(false);
DoRgt(false);
}
}
if( GetDistance(pChSpawn,psTarget) > stickDist) {
if( FindSpeed(pChSpawn) <= 0 ) {
DoFwd(true);
}
} else if( moveBack && GetDistance(pChSpawn,psTarget) < (stickDist-5.0) ) {
if( FindSpeed(pChSpawn) >= 0 ) {
DoBck(true);
}
} else if( FindSpeed(pChSpawn) > 0 ) {
DoFwd(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(GetCharInfo()->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 DoFwd(bool hold)
{
MQ2Globals::ExecuteCmd(FindMappableCommand("forward"),1,0);
if( !hold )
MQ2Globals::ExecuteCmd(FindMappableCommand("forward"),0,0);
}
void DoBck(bool hold)
{
MQ2Globals::ExecuteCmd(FindMappableCommand("back"),1,0);
if( !hold )
MQ2Globals::ExecuteCmd(FindMappableCommand("back"),0,0);
}
void DoLft(bool hold)
{
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_left"),1,0);
if( !hold )
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_left"),0,0);
}
void DoRgt(bool hold)
{
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_right"),1,0);
if( !hold )
MQ2Globals::ExecuteCmd(FindMappableCommand("strafe_right"),0,0);
}
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)
{
stickOn=false;
stickPaused=false;
stickHold=false;
setDist=false;
moveBehind=false;
prevMoveBehind=false;
moveBack=false;
mPause=false;
looseStick=false;
underwater=false;
stickTarget=NULL;
stickDistMod=0.0;
stickDistModP=1.0;
if( stopMoving ) {
DoFwd(false);
DoBck(false);
DoLft(false);
DoRgt(false);
}
stickText();
}
VOID CreateBinds()
{
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()
{
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();
MoveBindsLoaded=true;
}
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) {
if (!MoveBindsLoaded) {
CreateBinds();
MoveBindsLoaded=true;
}
Load_INI();
} else {
stickOn=false;
stickPaused=false;
stickHold=false;
setDist=false;
stickTarget=NULL;
bCircling=false;
}
}
float StateHeightMultiplier(DWORD StandState)
{
switch (StandState) {
case STANDSTATE_BIND:
case STANDSTATE_DUCK:
return 0.5f;
case STANDSTATE_SIT:
return 0.3f;
case STANDSTATE_FEIGN:
case STANDSTATE_DEAD:
return 0.1f;
case STANDSTATE_STAND:
default:
return 0.9f;
}
}



Code: Select all
#turbo 40
Sub Main
/declare ProvokeTimer timer outer
/declare OldExp float outer ${Me.PctExp}
/varset ProvokeTimer 60s
/attack on
:KillLoop
/if (${Target.ID}) {
/face fast
} else {
/echo Target something!
/return
}
/if (${Target.Distance}>14) /keypress up hold
/if (${Target.Distance}<13) /keypress up
| Not the best way to check to see if mob is facing away from me, but I was in a hurry. Basically, just
| keep provoking every 60s till mob starts running away.
/if ((${Target.ID})&&(${ProvokeTimer}<=0)&&(!${Target.Heading.Name.Equal[${Me.Heading.Name}]})) {
/disc Provoke
/varset ProvokeTimer 60s
}
/if (${Me.AbilityReady["Bash"]}) /doability "111" | This does Slam instead of bash.
/if (${Target.ID}) /goto :KillLoop
/echo You received ${Math.Calc[${Me.PctExp}-${OldExp}]}% exp for that kill.
/return

Call it what you want. Anything good on this site is VIP 10$ is not much.. Use your week worth of allowance and donate.CodeCaster wrote:Ahh didn't know it was for sale. So you can buy a copy or make this one work for you... Actually, I may be able to help you myself...
Here is the "/stick" macro that I use on my war. It's a little sloppy, but I just whipped it together in 15 minutes one night to avoid the clicky-frenzy that is playing a war. Heh.
Just make a hotkey that executes this macro and target a mob. It will run up to it, stay in range, provoke and slam. If you have any questions, don't be afraid to ask. I don't flame for stupid questions.Code: Select all
#turbo 40 Sub Main /declare ProvokeTimer timer outer /declare OldExp float outer ${Me.PctExp} /varset ProvokeTimer 60s /attack on :KillLoop /if (${Target.ID}) { /face fast } else { /echo Target something! /return } /if (${Target.Distance}>14) /keypress up hold /if (${Target.Distance}<13) /keypress up | Not the best way to check to see if mob is facing away from me, but I was in a hurry. Basically, just | keep provoking every 60s till mob starts running away. /if ((${Target.ID})&&(${ProvokeTimer}<=0)&&(!${Target.Heading.Name.Equal[${Me.Heading.Name}]})) { /disc Provoke /varset ProvokeTimer 60s } /if (${Me.AbilityReady["Bash"]}) /doability "111" | This does Slam instead of bash. /if (${Target.ID}) /goto :KillLoop /echo You received ${Math.Calc[${Me.PctExp}-${OldExp}]}% exp for that kill. /return

You are 100% correct about the defonition, BUT, there is no item being offered here. Even with VIP access there are no garuntees that you will find what you are looking for. Everything in VIP could be broken, and there are no garuntees that anyone will fix them. It's all voluntary. People volunteer to give money, and other people volunteer to fix and share.If money is required to obtain an item, it's a purchase, regardless of who sets the price. Sometimes a purchase is confused with a donation (such as in PoK when chanters won't C you unless you "donate") because the buyer is allowed to determine the price.