Thanks to Riddlerr we have had a great multifunction plugin. Since he is no longer playing / updating this plugin. I thought we could use it as an open source project and keep this great plugin alive. I will update it as I can but please post ideas and improvements. This threed is 100% to be focused on this plugin. Save the BS for somewhere else.
MAKE THESE CHANGES TO GET THIS TO WORK
(SOME FUNCTIONS MAY NEED TO BE UPDATED AND CAUSE CTD)
NOTE THE STRUCT CHANGES
eqdata.h and replace
/*0x24c*/ FLOAT Unknown0x24c[0x3];
with
/*0x24c*/ FLOAT SafeYLoc;
/*0x250*/ FLOAT SafeXLoc;
/*0x254*/ FLOAT SafeZLoc;
*
MQ2Main.h
#define CDisplay__MoveLocalPlayerToSafeCoords 0x00442D24
*
mq2commandapi.cpp and remove
if (!stricmp(Command,"/warp"))
{
Function=0;
}
/////////////////////////////////////////////////////
MAX_ZONES in EQData.h to 0x171 ***THINK THIS CHANGED***
or you won't be able to get to DoD zones.
12-10-05 OFFSETS
#define LocalCEverQuest__DoTheZone 0x49E64E
#define succorfunc 0x00442D24
Rich (BB code):
//MQ2RWarp.cpp
//Created By Riddlerr 7/1/05
//Teachers Pet ChainShift 10/1
//Teachers Pet Ghost 10/6
//Updated Code By Cosmic 10/8
//Directional Z Warp id_skew 10/13
//Maintained by board members 12/10/05
#include "../MQ2Plugin.h"
PreSetup("MQ2RWarp");
#undef ExactLocation
#undef zWarp
#undef DoWarp
#undef Warp
#undef SafeYLoc
#undef SafeXLoc
#undef SafeZLoc
#undef GateBind
#undef ZoneShift
#undef ZoneToGoTo
#define LocalCEverQuest__DoTheZone 0x49E64E
#define INFINITY ((int) pow(2, sizeof(int)*8-2)-1)
#ifdef PKT_UPDATE_POSITION
#undef PKT_UPDATE_POSITION
#endif
#define PKT_UPDATE_POSITION 0x14CB
#define PKT_CHANNEL_MESSAGE 0x1004
typedef struct
{
int connections[100]; // An array of edges which has this as the starting node
int numconnect;
} FWVertice;
typedef struct
{
int Zone;
char Name[50];
char Phrase[20][50];
int Destination[20];
float X,Y,Z;
int DestCnt;
} NPCTeleporter;
FWVertice *V=NULL;
NPCTeleporter NPCs[100];
int NPCCnt;
int* distances=NULL;
int* predecessor=NULL;
class LocalCEverQuest;
class LocalCEverQuest
{
public:
__declspec(dllexport) char * LocalCEverQuest::DoTheZone(int,char *,int,int,float,float,float,int);
};
#ifdef LocalCEverQuest__DoTheZone
FUNCTION_AT_ADDRESS(char * LocalCEverQuest::DoTheZone(int,char *,int,int,float,float,float,int),LocalCEverQuest__ DoTheZone);
#endif
LocalCEverQuest **ppLEQ;
#define pLEQ (*ppLEQ)
void Setup();
bool UseNPC(PSPAWNINFO pChar, int dest);
PLUGIN_API VOID OnZoned(PSPAWNINFO pChar, PCHAR szLine);
PLUGIN_API VOID OnPulse(VOID);
DWORD ListSimilarZones(PCHAR ZoneShortName);
VOID ChangeZones(PSPAWNINFO pChar, PCHAR szLine);
void FloydWarshall(FWVertice* vertices, int nodecount);
VOID FindPath(PSPAWNINFO pChar, PCHAR szLine);
VOID SimFade(PSPAWNINFO pChar, PCHAR szLine);
VOID SimGate(PSPAWNINFO pChar, PCHAR szLine);
VOID DoWarp(float y, float x, float z);
VOID Warp(PSPAWNINFO pChar, PCHAR szLine);
VOID zWarp(PSPAWNINFO pChar, PCHAR szLine);
VOID ExactLocation(PSPAWNINFO pChar);
VOID waypoint(PSPAWNINFO pChar, PCHAR szLine);
VOID Ghost(PSPAWNINFO pChar, PCHAR szLine);
bool ZoneChange=false;
float X,Y,Z;
int Heading;
int DestZone;
int ChainZone[100];
int ChainZoneCnt=0;
int DestType; // 0=use supplied coords 1=succorpoint
int ChainZoneType; // 0=use supplied coords 1=succorpoint
int ZoneReason;
int LastKnownZone=-1; //don't fire MyOnZoned when you first log in
void MyOnZoned(PSPAWNINFO pChar)
{
if (ChainZoneCnt>0)
{
if (pChar->Zone != ChainZone[ChainZoneCnt])
{
ChainZoneCnt=0;
return;
}
ChainZoneCnt--;
DestZone=ChainZone[ChainZoneCnt];
if (ChainZoneCnt==0) DestType=ChainZoneType;
WriteChatColor("Attempting ChainZone...", USERCOLOR_DEFAULT);
if ( UseNPC(pChar,DestZone) == false)
{
ZoneChange=true;
}
}
return;
}
PLUGIN_API VOID OnPulse(VOID)
{
PSPAWNINFO pChar = NULL;
if (ppCharSpawn && pCharSpawn) {
pChar = (PSPAWNINFO)pCharSpawn;
if ((pChar) && (!gZoning))
{
if (LastKnownZone == -1) LastKnownZone=pChar->Zone;
if (pChar->Zone != LastKnownZone)
{
LastKnownZone=pChar->Zone;
MyOnZoned(pChar);
}
}
}
char aa[100]="test";
if(ZoneChange)
{
ZoneChange=false;
pLEQ->DoTheZone(DestZone,aa,DestType,ZoneReason,Y,X,Z,He ading);
}
return;
}
DWORD ListSimilarZones(PCHAR PartialName)
{
CHAR szMsg[MAX_STRING] = "Bad Zone.ShortName. Suggest: ";
CHAR szName[MAX_STRING] = {0};
char *partial,*longname;
PZONELIST pZone = NULL;
partial=_strlwr(_strdup(PartialName));
if (!ppWorldData | !pWorldData) return -1;
for (int nIndex=0; nIndex < MAX_ZONES+1; nIndex++) {
pZone = ((PWORLDDATA)pWorldData)->ZoneArray[nIndex];
if(pZone )
{
longname=_strlwr(_strdup(pZone->LongName));
if (strstr(longname,partial)) {
sprintf(szName,"%s(%s) ",pZone->LongName,pZone->ShortName);
if ((strlen(szMsg)+strlen(szName))>=300)
{
WriteChatColor(szMsg,USERCOLOR_DEFAULT);
szMsg[0]=0;
}
strcat(szMsg,szName);
}
free(longname);
}
}
WriteChatColor(szMsg,USERCOLOR_DEFAULT);
free(partial);
return -1;
}
VOID Zone(PSPAWNINFO pChar, PCHAR szLine)
{
CHAR szMsg[MAX_STRING] = {0};
CHAR szParam[MAX_STRING] = {0};
CHAR sZoneName[MAX_STRING] ={0};
CHAR sWPName[MAX_STRING] ={0};
CHAR sKeyData[MAX_STRING]={0};
DWORD ZoneToGoTo;
int rLen;
int i,j,cnt=0;
bool IgnoreChain=false;
int Param=1;
GetArg(szParam,szLine,Param);
if (_stricmp(szParam,"setwp")==0)
{
Param++;
GetArg(sWPName,szLine,Param);
if (sWPName[0]==0)
{
WriteChatColor("Usage: /zone setwp <WayPointName>", CONCOLOR_RED);
return;
}
sprintf(sKeyData,"%.2f %.2f %2.f %d",pChar->Y,pChar->X,pChar->Z,(int)pChar->Heading);
WritePrivateProfileString(GetShortZone(pChar->Zone), sWPName, sKeyData, INIFileName);
WriteChatColor("Waypoint recorded", USERCOLOR_DEFAULT);
return;
}
if (_stricmp(szParam,"clearwp")==0)
{
Param++;
GetArg(sWPName,szLine,Param);
if (sWPName[0]==0)
{
WriteChatColor("Usage: /zone clearwp <WayPointName>", CONCOLOR_RED);
return;
}
WritePrivateProfileString(GetShortZone(pChar->Zone), sWPName, NULL, INIFileName);
WriteChatColor("Waypoint cleared", USERCOLOR_DEFAULT);
return;
}
if (_stricmp(szParam,"force")==0)
{
IgnoreChain=true;
Param++;
}
GetArg(sZoneName,szLine,Param++);
ZoneToGoTo = GetZoneID(sZoneName);
if (ZoneToGoTo == -1) {
ListSimilarZones(sZoneName);
return;
}
Setup();
if (IgnoreChain==false)
{
i=pChar->Zone;
j=ZoneToGoTo;
if (distances[i*MAX_ZONES+j]==0)
{
WriteChatColor("Poof! You are already there.", CONCOLOR_RED);
return;
}
if (distances[i*MAX_ZONES+j]==INFINITY)
{
WriteChatColor("I don't know a route to that zone.", CONCOLOR_RED);
return;
}
}
GetArg(sWPName,szLine,Param++);
if (sWPName[0]!=0)
{
CHAR sDefault[MAX_STRING]="none";
GetPrivateProfileString(sZoneName,sWPName, sDefault, sKeyData, MAX_STRING, INIFileName);
if (_stricmp(sKeyData,"none")==0)
{
rLen=GetPrivateProfileString(sZoneName,NULL, sDefault, sKeyData, MAX_STRING, INIFileName);
for (int i=0;i<rLen-1;i++) if (sKeyData==0) sKeyData=',';
sprintf(szMsg,"Bad Waypoint. Suggest: %s",sKeyData);
WriteChatColor(szMsg,USERCOLOR_DEFAULT);
return;
}
sscanf(sKeyData,"%f %f %f %d",&Y,&X,&Z,&Heading);
DestType=0;
}
else
{
sprintf(sWPName,"default");
CHAR sDefault[MAX_STRING]="none";
GetPrivateProfileString(sZoneName,sWPName, sDefault, sKeyData, MAX_STRING, INIFileName);
if (_stricmp(sKeyData,"none")!=0)
{
sscanf(sKeyData,"%f %f %f %d",&Y,&X,&Z,&Heading);
DestType=0;
}
else
{
Y=pChar->Y;
X=pChar->X;
Z=pChar->Z;
Heading = (int)pChar->Heading;
DestType=1;
}
}
ChainZoneCnt=0; //reset in case we failed to finish previous chain-zone attempt
if (IgnoreChain==false)
{
while (i!=j)
{
ChainZone[ChainZoneCnt++]=j;
j=predecessor[i*MAX_ZONES+j];
}
if (ChainZoneCnt>1)
{
ChainZoneType=DestType;
DestType=1;
}
DestZone = ChainZone[--ChainZoneCnt];
}
else
{
DestZone=ZoneToGoTo;
}
sprintf(szMsg,"Zoneing...");
WriteChatColor(szMsg,USERCOLOR_DEFAULT);
ZoneReason=0;
if (UseNPC(pChar,DestZone) == false) ZoneChange=true;
return;
}
VOID FindPath(PSPAWNINFO pChar, PCHAR szLine)
{
CHAR sDest[MAX_STRING]={0};
int ZoneToGoTo;
int i,j,cnt=0,stops[100];
GetArg(sDest,szLine,1);
if (sDest[0]==0)
{
WriteChatColor("Usage: /FindPath <ShortZoneName>", CONCOLOR_RED);
return;
}
ZoneToGoTo = GetZoneID(sDest);
if (ZoneToGoTo == -1) {
ListSimilarZones(sDest);
return;
}
Setup();
i=pChar->Zone;
j=ZoneToGoTo;
if (distances[i*MAX_ZONES+j]==0)
{
WriteChatColor("Poof! You are already there.", CONCOLOR_RED);
return;
}
if (distances[i*MAX_ZONES+j]==INFINITY)
{
WriteChatColor("I don't know a route to that zone.", CONCOLOR_RED);
return;
}
WriteChatColor("My path:", CONCOLOR_RED);
while (i!=j)
{
stops[cnt++]=j;
j=predecessor[i*MAX_ZONES+j];
}
while (cnt>0)
{
cnt--;
WriteChatColor(GetShortZone(stops[cnt]),USERCOLOR_DEFAULT);
}
}
void Setup()
{
char sKey[300];
char sKeyData[300];
char *p;
int i;
if (distances!=NULL) free(distances);
if (predecessor!=NULL) free(predecessor);
if (V!=NULL) free(V);
V = (FWVertice *)malloc(MAX_ZONES*sizeof(FWVertice));
int tmp[100],cnt;
for (i=0;i<MAX_ZONES;i++)
{
sprintf(sKey,"%d",i);
V.numconnect=0;
GetPrivateProfileString("ZoneConnections",sKey,"none",sKeyData,300,INIFileName);
if (_stricmp(sKeyData,"none")!=0)
{
strtok(sKeyData,"\"");
strtok(NULL,"\"");
cnt=0;
while ( (p=strtok(NULL,",")) != NULL)
{
tmp[cnt++]=atoi(p);
}
V.numconnect=cnt+1;
for (int j=0;j<cnt;j++) V.connections[j]=tmp[j];
}
V.connections[V.numconnect++]=GetCharInfo2()->ZoneBoundID; //always connected to my bind point
}
//NPCTeleporter support
NPCCnt=0;
for (i=0;i<100;i++)
{
sprintf(sKey,"%d",(i+1));
GetPrivateProfileString("NPCTeleporters",sKey,"none",sKeyData,300,INIFileName);
if (_stricmp(sKeyData,"none")==0) break;
NPCCnt++;
NPCs.Zone=atoi(strtok(sKeyData," \""));
strcpy(NPCs.Name,strtok(NULL,"\""));
NPCs.Y=(float)atof(strtok(NULL," "));
NPCs.X=(float)atof(strtok(NULL," "));
NPCs.Z=(float)atof(strtok(NULL," "));
NPCs.DestCnt=0;
p=strtok(NULL," \"");
while (p!=NULL)
{
NPCs.Destination[NPCs.DestCnt]=atoi(p);
strcpy(NPCs.Phrase[NPCs.DestCnt],strtok(NULL,"\""));
V[NPCs.Zone].connections[V[NPCs.Zone].numconnect++]=NPCs.Destination[NPCs.DestCnt];
NPCs.DestCnt++;
p=strtok(NULL," \"");
}
}
FloydWarshall(V,MAX_ZONES);
}
bool UseNPC(PSPAWNINFO pChar,int dest)
{
for (int i=0;i<NPCCnt;i++)
{
if (NPCs.Zone != pChar->Zone) continue;
for (int j=0;j<NPCs.DestCnt;j++)
{
if (NPCs.Destination[j]==dest)
{
//Code borrowed directly from MQ2CSum
// setup move packet
struct _MOVEPKT {
/*0000*/ unsigned short SpawnID;
/*0002*/ unsigned short TimeStamp;
/*0004*/ float Y;
/*0008*/ float DeltaZ;
/*0012*/ float DeltaY;
/*0016*/ float DeltaX;
/*0020*/ int Animation:10;
/*0020*/ int DeltaHeading:10;
/*0020*/ int padding0020:12;
/*0024*/ float X;
/*0028*/ float Z;
/*0032*/ int Heading:12;
/*0032*/ int padding1_0032:10;
/*0032*/ int padding2_0032:10;
} P; // 36
struct _MSGPACKET {
/*0000*/ char target[64];
/*0064*/ char sender[64];
/*0128*/ unsigned int language;
/*0132*/ unsigned int channel;
/*0136*/ char padding136[8];
/*0144*/ unsigned int languageskill;
/*0148*/ char message[100];
} M;
// init packets
ZeroMemory(&P, sizeof(P));
ZeroMemory(&M, sizeof(M));
P.SpawnID = (unsigned short)pChar->SpawnID;
P.Heading = (unsigned int)(pChar->Heading * 4);
PSPAWNINFO psTarget = NULL;
Target(pChar,NPCs.Name);
if (ppTarget && pTarget) {
psTarget = (PSPAWNINFO)pTarget;
}
if (psTarget)
{
strcpy(M.target,psTarget->Name);
}
strcpy(M.sender,pChar->Name);
M.channel=8;
M.languageskill=100;
// jump to
P.Z = NPCs.Z;
P.Y = NPCs.Y;
P.X = NPCs.X;
SendEQMessage(PKT_UPDATE_POSITION, &P, sizeof(P));
sprintf(M.message,"%s",NPCs.Phrase[j]);
SendEQMessage(PKT_CHANNEL_MESSAGE,&M,sizeof(M));
return true;
}
}
}
return false;
}
void FloydWarshall(FWVertice* vertices, int nodecount) // Vertices numbered from 0 to nodecount-1
{
distances = (int*) malloc(nodecount*nodecount*sizeof(int)*8);
predecessor = (int*) malloc(nodecount*nodecount*sizeof(int)*8);
int i,j,k;
for(i = 0; i < nodecount; i++)
{
for(j = 0; j < nodecount; j++)
{
distances[i*nodecount+j] = 0;
predecessor[i*nodecount+j] = i;
}
}
for(i = 0; i < nodecount; i++)
{
for(j = 0; j < vertices.numconnect; j++)
{
distances[i*nodecount + vertices.connections[j]] =1;
// vertices.connections[j].weight;
}
for(j = 0; j < nodecount; j++)
{
if(!distances[i*nodecount+j] && (i^j))
// i ^ j returns 0 if they are equal
{
distances[i*nodecount+j] = INFINITY;
}
}
}
for(k = 0; k < nodecount; k++)
{
for(i = 0; i < nodecount; i++)
{
for(j = 0; j < nodecount; j++)
{
if(distances[i*nodecount+j] > distances[i*nodecount+k] + distances[k*nodecount+j])
{
distances[i*nodecount+j] = distances[i*nodecount+k] + distances[k*nodecount+j];
predecessor[i*nodecount+j] = predecessor[k*nodecount+j];
}
}
}
}
}
VOID Gate(PSPAWNINFO pChar, PCHAR szLine)
{
CHAR szMsg[MAX_STRING] = {0};
PCHARINFO2 pChar2 = GetCharInfo2();
sprintf(szMsg,"Gating...");
WriteChatColor(szMsg,USERCOLOR_DEFAULT);
DestZone=pChar2->ZoneBoundID;
DestType=0;
ZoneReason=11;
Y=pChar2->ZoneBoundY;
X=pChar2->ZoneBoundX;
Z=pChar2->ZoneBoundZ;
Heading=0;
ZoneChange=true;
return;
}
VOID Fade(PSPAWNINFO pChar, PCHAR szLine)
{
CHAR szMsg[MAX_STRING] = {0};
if (pChar->Instance != 0)
{
DestZone = *((int *)(&(pChar->Instance)-1));
}
else
{
DestZone = pChar->Zone;
}
sprintf(szMsg,"Fading...");
WriteChatColor(szMsg,USERCOLOR_DEFAULT);
DestType=0;
ZoneReason=0;
Y=pChar->Y;
X=pChar->X;
Z=pChar->Z;
Heading =(int)pChar->Heading;
ZoneChange=true;
return;
}
VOID ExactLocation(PSPAWNINFO pChar, PCHAR szLine)
{ CHAR LocMsg[MAX_STRING] = {0};
sprintf(LocMsg, "Your location is %3.6f, %3.6f, %3.6f", pChar->Y, pChar->X, pChar->Z);
WriteChatColor(LocMsg);
return;
}
VOID zWarp(PSPAWNINFO pChar, PCHAR szLine)
{ CHAR Z[MAX_STRING] = {0};
GetArg(Z,szLine,1);
float MyY = pChar->Y;
float MyX = pChar->X;
if (Z[0]==0) {
WriteChatColor("Usage: /zwarp <dist>", CONCOLOR_RED);
return;
}
float NewZ = pChar->Z;
NewZ = NewZ + (FLOAT)atof(Z);
DoWarp(MyY, MyX, NewZ);
return;
}
VOID Warp(PSPAWNINFO pChar, PCHAR szLine)
{
static float LastY;
static float LastX;
static float LastZ;
bRunNextCommand = TRUE;
PSPAWNINFO psTarget = NULL;
PZONEINFO Zone = (PZONEINFO)pZoneInfo;
CHAR command[MAX_STRING]; GetArg(command,szLine,1);
CHAR Y[MAX_STRING]; GetArg(Y,szLine,2);
CHAR X[MAX_STRING]; GetArg(X,szLine,3);
CHAR Z[MAX_STRING]; GetArg(Z,szLine,4);
if (
stricmp(command, "succor") != 0 &&
stricmp(command, "loc") != 0 &&
stricmp(command, "last") != 0 &&
stricmp(command, "target") != 0 &&
stricmp(command, "dir") != 0 &&
stricmp(command, "wp") != 0
) {
WriteChatColor("Usage: /warp <succor|last|loc <y x z>|dir <dist>|target|wp name>", CONCOLOR_RED);
return;
} else {
if (!stricmp(command,"target")) {
if (ppTarget && pTarget) {
psTarget = (PSPAWNINFO)pTarget;
}
if (!psTarget) {
WriteChatColor("You must have a target for /warp target.", CONCOLOR_RED);
return;
}
float TargetZ = float (psTarget->Z);
float TargetY = float (psTarget->Y);
float TargetX = float (psTarget->X);
LastY = TargetY;
LastX = TargetX;
LastZ = TargetZ;
DoWarp(TargetY, TargetX, TargetZ);
} else if (!stricmp(command,"succor")) {
static float north = 0;
((PSPAWNINFO)pCharSpawn)->Heading = north;
DWORD MLPTSC = CDisplay__MoveLocalPlayerToSafeCoords;
__asm call dword ptr [MLPTSC];
return;
} else if (!stricmp(command,"loc")) {
if ((Y[0] == 0) || (X[0] == 0) || (Z[0] == 0))
{
WriteChatColor("You must provide <y> <x> <z> if going to a location.", CONCOLOR_RED);
return;
}
LastY = (float)atof(Y);
LastX = (float)atof(X);
LastZ = (float)atof(Z);
DoWarp((float)atof(Y), (float)atof(X), (float)atof(Z));
return;
} else if (!stricmp(command,"last")) {
if ((LastY==0) || (LastX==0) || (LastZ==0))
{
WriteChatColor("You must have warped before to use this command!.", CONCOLOR_RED);
return;
}
DoWarp(LastY, LastX, LastZ);
return;
} else if (!stricmp(command,"dir")) {
if (Y[0]==0) {
WriteChatColor("You MUST provide <dist> if going in your current direction.", CONCOLOR_RED);
return;
}
double Heading=pChar->Heading/(256/PI);
double CameraAngle=pChar->CameraAngle/(256/PI);
float posX=(float)(atof(Y)*sin(Heading)*cos(CameraAngle) +pChar->X);
float posY=(float)(atof(Y)*cos(Heading)*cos(CameraAngle) +pChar->Y);
float posZ=(float)(atof(Y)*sin(CameraAngle)+pChar->Z);
DoWarp(posY, posX, posZ);
return;
}
{
char szLoc[MAX_STRING] = {0};
char szName[MAX_STRING] = {0};
char WaypointsINI[MAX_STRING] = {0};
char szBuf[MAX_STRING] = {0};
char szHeading[MAX_STRING] = {0};
char szDestWarpX[MAX_STRING] = {0};
char szDestWarpY[MAX_STRING] = {0};
char szDestWarpZ[MAX_STRING] = {0};
char szMsg[MAX_STRING] = {0};
sprintf(WaypointsINI,"%s\\waypoints.ini",gszINIPath);
GetArg(szName, szLine, 2);
if(!strnicmp(szName, "", 1))
{
WriteChatColor("You didn't specify a waypoint.", COLOR_LIGHTGREY);
}
else
{
GetPrivateProfileString(Zone->ShortName,szName,"",szLoc,MAX_STRING,WaypointsINI);
if (!strnicmp(szLoc, "", 1))
{
sprintf(szMsg, "Waypoint \'%s\' does not exist.", szName);
WriteChatColor(szMsg, COLOR_LIGHTGREY);
}
else
{
// get destination locs
GetArg(szDestWarpX, szLoc, 2);
GetArg(szDestWarpY, szLoc, 1);
GetArg(szDestWarpZ, szLoc, 3);
// get heading
GetArg(szBuf, szLoc, 4);
GetArg(szHeading,szBuf,1,0,0,0,':');
DoWarp((float)atof(szDestWarpY), (float)atof(szDestWarpX), (float)atof(szDestWarpZ));
}
}
}
}
}
VOID DoWarp(float y, float x, float z)
{
PZONEINFO Zone = (PZONEINFO)pZoneInfo;
float SafeY = Zone->SafeYLoc;
float SafeX = Zone->SafeXLoc;
float SafeZ = Zone->SafeZLoc;
Zone->SafeYLoc = y;
Zone->SafeXLoc = x;
Zone->SafeZLoc = z;
CHAR szMsg[MAX_STRING] = {0};
sprintf(szMsg, "Warping to: %3.2f, %3.2f, %3.2f.", Zone->SafeYLoc, Zone->SafeXLoc, Zone->SafeZLoc);
WriteChatColor(szMsg, COLOR_PURPLE);
DWORD MLPTSC = CDisplay__MoveLocalPlayerToSafeCoords;
__asm call dword ptr [MLPTSC];
Zone->SafeYLoc = SafeY;
Zone->SafeXLoc = SafeX;
Zone->SafeZLoc = SafeZ;
}
VOID waypoint(PSPAWNINFO pChar, PCHAR szLine)
{
PZONEINFO Zone = (PZONEINFO)pZoneInfo;
CHAR WaypointsINI[MAX_STRING] = {0};
CHAR szTemp[10] = {0};
CHAR szData[MAX_STRING] = {0};
CHAR szDesc[MAX_STRING] = {0};
CHAR szName[MAX_STRING] = {0};
CHAR szCommand[MAX_STRING] = {0};
CHAR szBuffer[MAX_STRING] = {0};
CHAR szMsg[MAX_STRING] = {0};
CHAR WaypointList[MAX_STRING*10] = {0};
PCHAR pWaypointList = WaypointList;
CHAR szKey[MAX_STRING] = {0};
CHAR szValue[MAX_STRING] = {0};
sprintf(WaypointsINI,"%s\\waypoints.ini",gszINIPath);
GetArg(szCommand, szLine, 1);
if (!strnicmp(szCommand, "add", 3))
{
GetArg(szName, szLine, 2);
if(!strnicmp(szName, "", 1))
{
WriteChatColor("You didn't specify a name for the waypoint.", COLOR_LIGHTGREY);
}
else
{
GetPrivateProfileString(Zone->ShortName,szName,"",szBuffer,MAX_STRING,WaypointsINI);
if (!strnicmp(szBuffer, "", 1))
{
GetArg(szDesc, szLine, 3);
sprintf(szData, "%1.2f %1.2f %1.2f %1.2f:%s", pChar->Y, pChar->X, pChar->Z, (float)pChar->Heading*0.703125f, szDesc);
WritePrivateProfileString(Zone->ShortName,szName,szData,WaypointsINI);
sprintf(szMsg, "Waypoint \'%s\' added.", szName);
WriteChatColor(szMsg, COLOR_LIGHTGREY);
}
else
{
sprintf(szMsg, "Waypoint \'%s\' already exists.", szName);
WriteChatColor(szMsg, COLOR_LIGHTGREY);
}
}
}
else if (!strnicmp(szCommand, "delete", 6))
{
GetArg(szName, szLine, 2);
if(!strnicmp(szName, "", 1))
{
WriteChatColor("You didn't specify a waypoint to delete.", COLOR_LIGHTGREY);
}
else
{
GetPrivateProfileString(Zone->ShortName,szName,"",szBuffer,MAX_STRING,WaypointsINI);
if (!strnicmp(szBuffer, "", 1))
{
sprintf(szMsg, "Waypoint \'%s\' does not exist.", szName);
WriteChatColor(szMsg, COLOR_LIGHTGREY);
}
else
{
WritePrivateProfileString(Zone->ShortName,szName,"",WaypointsINI);
// rewrite the section minus the deleted waypoint
GetPrivateProfileSection(Zone->ShortName,WaypointList,MAX_STRING*10,WaypointsINI) ;
WritePrivateProfileSection(Zone->ShortName,"",WaypointsINI);
pWaypointList = WaypointList;
while (pWaypointList[0]!=0)
{
GetArg(szKey,pWaypointList,1,0,0,0,'=');
GetArg(szValue,pWaypointList,2,0,0,0,'=');
if (strnicmp(szValue, "", 1))
{
WritePrivateProfileString(Zone->ShortName,szKey,szValue,WaypointsINI);
}
pWaypointList+=strlen(pWaypointList)+1;
}
sprintf(szMsg, "Waypoint \'%s\' deleted.", szName);
WriteChatColor(szMsg, COLOR_LIGHTGREY);
}
}
}
else if (!strnicmp(szCommand, "list", 4))
{
GetPrivateProfileSection(Zone->ShortName,WaypointList,MAX_STRING*10,WaypointsINI) ;
pWaypointList = WaypointList;
sprintf(szMsg, "Waypoints for %s", Zone->LongName);
WriteChatColor(szMsg, CONCOLOR_YELLOW);
while (pWaypointList[0]!=0)
{
GetArg(szName,pWaypointList,1,0,0,0,'=');
GetArg(szData,pWaypointList,2,0,0,0,'=');
GetArg(szDesc,szData,2,0,0,0,':');
if (strnicmp(szDesc,"",1))
{
sprintf(szMsg, "- %s ( %s )", szName, szDesc);
}
else
{
sprintf(szMsg, "- %s", szName);
}
WriteChatColor(szMsg, COLOR_LIGHTGREY);
pWaypointList+=strlen(pWaypointList)+1;
}
}
else
{
WriteChatColor("Invalid syntax. Usage:", COLOR_LIGHTGREY);
WriteChatColor("/waypoint add name", COLOR_LIGHTGREY);
WriteChatColor("/waypoint delete name", COLOR_LIGHTGREY);
WriteChatColor("/waypoint list", COLOR_LIGHTGREY);
}
}
VOID Ghost(PSPAWNINFO pChar, PCHAR szLine)
{
DWORD SpawnID;
if((!strcmp(szLine,"on")) && (GetCharInfo()->pSpawn->SpawnID != 0))
{
pTarget = NULL;
SpawnID = GetCharInfo()->pSpawn->SpawnID;
GetCharInfo()->pSpawn->SpawnID = 0;
WriteChatColor("You are now ghosting.",USERCOLOR_DEFAULT);
}
if(!strcmp(szLine,"off"))
{
pTarget = NULL;
GetCharInfo()->pSpawn->SpawnID = SpawnID;
WriteChatColor("You are no longer ghosting.",USERCOLOR_DEFAULT);
}
}
PLUGIN_API VOID InitializePlugin(VOID)
{
DebugSpewAlways("Initializing MQ2RWarp");
AddCommand("/warp",Warp);
AddCommand("/zwarp",zWarp);
AddCommand("/exactloc",ExactLocation);
AddCommand("/waypoint", waypoint);
AddCommand("/ghost",Ghost);
ppLEQ=(LocalCEverQuest**)pinstCEverQuest;
AddCommand("/zone",Zone);
AddCommand("/gate",Gate);
AddCommand("/fade",Fade);
AddCommand("/findpath",FindPath);
}
PLUGIN_API VOID ShutdownPlugin(VOID)
{
DebugSpewAlways("Shutting down MQ2RWarp");
RemoveCommand("/warp");
RemoveCommand("/exactloc");
RemoveCommand("/zwarp");
RemoveCommand("/waypoint");
RemoveCommand("/zone");
RemoveCommand("/gate");
RemoveCommand("/fade");
RemoveCommand("/ghost");
}
MAKE THESE CHANGES TO GET THIS TO WORK
(SOME FUNCTIONS MAY NEED TO BE UPDATED AND CAUSE CTD)
NOTE THE STRUCT CHANGES
eqdata.h and replace
/*0x24c*/ FLOAT Unknown0x24c[0x3];
with
/*0x24c*/ FLOAT SafeYLoc;
/*0x250*/ FLOAT SafeXLoc;
/*0x254*/ FLOAT SafeZLoc;
*
MQ2Main.h
#define CDisplay__MoveLocalPlayerToSafeCoords 0x00442D24
*
mq2commandapi.cpp and remove
if (!stricmp(Command,"/warp"))
{
Function=0;
}
/////////////////////////////////////////////////////
MAX_ZONES in EQData.h to 0x171 ***THINK THIS CHANGED***
or you won't be able to get to DoD zones.
12-10-05 OFFSETS
#define LocalCEverQuest__DoTheZone 0x49E64E
#define succorfunc 0x00442D24
Last edited:

