Some Map enhancements for /highlight

A forum for feature requests/discussions and user submitted patches that improve MQ2

Moderator: MacroQuest Developers

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Some Map enhancements for /highlight

Post by JudgeD » Sat Dec 26, 2015 8:37 pm

Just wanted to share some tweaks I made to MQ2Map that some may find useful.

1) /high size ##
This changes the size of your highlights. Default value is 100.

2) /high pulse
This toggles pulsing highlights, which makes them stick out way easier. The pulse changes the size of the marker between 50% - 150% of the normal size. The pulsing is really an elegant looking thing, I really enjoy it since I added it, please check it out and let me know what you think.

Both of these settings are default to the standard map settings, so new users won't experience them unless set explicitly.

I also made it so these settings will persist in your MQ2Map.ini file.

Also please note, I'm not using the vanilla version of MQ2Map, so the parts I changed will probably just need to be plugged into the vanilla version, I assume it'll be easy. These changes aren't hard and I'm not a professional C++ dev.

MQ2Map.cpp

Code: Select all

// MQ2Map.cpp : Defines the entry point for the DLL application.
//

// PLUGIN_API is only to be used for callbacks.  All existing callbacks at this time
// are shown below. Remove the ones your plugin does not use.  Always use Initialize
// and Shutdown for setup and cleanup, do NOT do it in DllMain.


#include "../MQ2Plugin.h"
#include "MQ2Map.h"
PreSetup("MQ2Map");

long repeatLast = 0;
long repeatInterval = 10;
clock_t highPulseRepeatLast = clock();
long highPulseRepeatIntervalMillis = 50;
unsigned long bmMapRefresh = 0;

BOOL repeatMaphide = FALSE;
BOOL repeatMapshow = FALSE;

DWORD HighlightColor=0xFF700070;
DWORD HighlightSIDELEN = 100;
BOOL HighlightPulse = FALSE;
BOOL HighlightPulseIncreasing = TRUE;
int HighlightPulseIndex = 0;
DWORD HighlightPulseDiff = HighlightSIDELEN / 10;

CHAR MapSpecialClickString[16][MAX_STRING]=
{
    "",// unused, will always target
    "",//SHIFT 
    "/maphide id %i",//CTRL
    "",//CTRL|SHIFT
    "/highlight id %i",//LALT 
    "",//LALT|SHIFT
    "",//LALT|CTRL
    "",//LALT|SHIFT|CTRL
    "",//RALT
    "",//RALT|SHIFT
    "",//RALT|CTRL
    "",//RALT|SHIFT|CTRL
    "",//RALT|LALT
    "",//RALT|LALT|SHIFT
    "",//RALT|LALT|CTRL
    "" //RALT|LALT|SHIFT|CTRL
};

CHAR MapNameString[MAX_STRING]={"%N"};
CHAR MapTargetNameString[MAX_STRING]={"%N"};
CHAR mapshowStr[MAX_STRING] = {""};
CHAR maphideStr[MAX_STRING] = {""};
SEARCHSPAWN MapFilterCustom = {0};
SEARCHSPAWN MapFilterNamed = {0};
MAPFILTER MapFilterOptions[] = {
    {"All",          TRUE,-1,          TRUE,MAPFILTER_Invalid,TRUE,  "Enables/disables map functions"},
    {"PC",           FALSE,0xFF00FF,   TRUE,MAPFILTER_All,TRUE,      "Displays PCs"},
    {"PCConColor",   FALSE,-1,         TRUE,MAPFILTER_PC,FALSE,      "Displays PCs in consider colors"},
    {"Group",        FALSE,0x0080C0,   TRUE,MAPFILTER_PC,FALSE,      "Displays group members in a specific color"},
    {"Mount",        FALSE,0x707070,   TRUE,MAPFILTER_All,TRUE,      "Displays mounts"},
    {"NPC",          FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays NPCs"},
    {"NPCConColor",  FALSE,-1,         TRUE,MAPFILTER_NPC,FALSE,     "Displays NPCs in consider colors"},
    {"Untargetable", FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays Untargetable NPCs"},
    {"Pet",          FALSE,0x707070,   TRUE,MAPFILTER_All,TRUE,      "Displays pets"},
    {"Corpse",       FALSE,0x00C000,   TRUE,MAPFILTER_All,TRUE,      "Displays corpses"},
    {"Chest",        FALSE,0xC08000,   TRUE,MAPFILTER_All,TRUE,      "Displays chestesses"},
    {"Trigger",      FALSE,0xC08000,   TRUE,MAPFILTER_All,TRUE,      "Displays hidden triggers"},
    {"Trap",         FALSE,0xC08000,   TRUE,MAPFILTER_All,TRUE,      "Displays hidden traps"},
    {"Timer",        FALSE,0xC08000,   TRUE,MAPFILTER_All,TRUE,      "Displays hidden timers"},
    {"Ground",       FALSE,0xC0C0C0,   TRUE,MAPFILTER_All,TRUE,      "Displays ground items"},
    {"Target",       FALSE,0xC00000,   TRUE,MAPFILTER_All,FALSE,     "Displays your target"},
    {"TargetLine",   FALSE,0x808080,   TRUE,MAPFILTER_Target,FALSE,  "Displays a line to your target"},
    {"TargetRadius", FALSE,0x808080,   FALSE,MAPFILTER_Target,FALSE, "Sets radius of a circle around your target to # (omit or set to 0 to disable)"},
    {"TargetMelee",  FALSE,0xFF8080,   FALSE,MAPFILTER_Target,FALSE, "Draws a melee-range circle around your target"},
    {"Vector",       FALSE,-1,         TRUE,MAPFILTER_All,TRUE,      "Displays heading vectors"},
    {"Custom",       FALSE,-1,         FALSE,MAPFILTER_All,TRUE,     "Sets custom filter (omit to disable)"},
    {"CastRadius",   FALSE,0x808080,   FALSE,MAPFILTER_All,FALSE,    "Sets radius of casting circle to # (omit or set to 0 to disable)"},
    {"NormalLabels", 0,-1,             TRUE,MAPFILTER_Invalid,FALSE, "Toggles non-MQ2 label display"},
    {"Menu",         FALSE,-1,         TRUE,MAPFILTER_Invalid,FALSE, "Allows display of right-click context menu"},
    {"SpellRadius",  FALSE,0x00C000,   FALSE,MAPFILTER_All,FALSE,    "Sets radius of 2nd casting circle to # (omit or set to 0 to disable)"},
    {"Aura",         FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays Auras"},
    {"Object",       FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays inanimate objects"},
    {"Banner",       FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays banners"},
    {"Campfire",     FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays campfires"},
    {"PCCorpse",     FALSE,0x00C000,   TRUE,MAPFILTER_All,TRUE,	     "Displays PC corpses, when corpse setting is on"},
    {"NPCCorpse",    FALSE,0x00C000,   TRUE,MAPFILTER_All,TRUE,      "Displays NPC corpses, when corpse setting is on"},
    {"Mercenary",    FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays mercenaries"},
    {"Named",        FALSE,0x404040,   TRUE,MAPFILTER_All,TRUE,      "Displays named NPCs"},
    {"Marker",        FALSE,-1,         FALSE,MAPFILTER_All,TRUE,  "Displays marker (mobtype triangle/square/diamond size)"},
    {"TargetPath",   FALSE,-1,         TRUE,MAPFILTER_Target,FALSE,  "Draws EQ Path to selected target"},
    {NULL,           FALSE,-1,         FALSE,MAPFILTER_Invalid,FALSE,  NULL}
};


PCSIDLWNDVFTABLE CMyMapViewWnd__OldvfTable=0;
PCSIDLWNDVFTABLE MapViewMap_OldvfTable=0;
DWORD CMyMapViewWnd__OldDestructor=0;
DWORD CMyMapViewWnd__OldHandleRButtonDown=0;
DWORD CMyMapViewWnd__OldPostDraw=0;
DWORD MapViewMap__OldHandleRButtonDown=0;

DWORD __declspec(naked) CMyMapViewWnd__Destructor(const BOOL Deallocate)
{
    __asm {   
        push ecx;
        push eax;
    }

    if (CMyMapViewWnd__OldvfTable && MapViewMap_OldvfTable) { 
        // make our own little stack frame here
        // operator delete assumes that it is there
        // it uses (unnecessarily) ebp-4
        __asm {
            push    ebp
                push    eax
                push    eax
                mov            ebp, esp
        }
        delete pMapViewWnd->pvfTable;
        pMapViewWnd->pvfTable=CMyMapViewWnd__OldvfTable;
        CMyMapViewWnd__OldvfTable = NULL;
        delete ((PEQMAPWINDOW)pMapViewWnd)->pMapViewMapVfTable;
        ((PEQMAPWINDOW)pMapViewWnd)->pMapViewMapVfTable = MapViewMap_OldvfTable;
        MapViewMap_OldvfTable = NULL;
        __asm {
            pop     eax
                pop     eax
                pop     ebp
        }
    }

    __asm {
        pop eax;
        pop ecx;
        jmp [CMyMapViewWnd__OldDestructor];
    }
}

bool RButtonDown()
{
    if (pCurrentMapLabel)
    {
        return MapSelectTarget();
    }
    if (!IsOptionEnabled(MAPFILTER_ContextMenu))
        return false;
    return true;
}

VOID __declspec(naked) MapViewMap__HandleRButtonDown(DWORD point, DWORD unknown)
{
    __asm {   
        push ecx;
        push eax;
    }
    if (RButtonDown())
    {
        __asm {
            pop eax;
            pop ecx;
            jmp [MapViewMap__OldHandleRButtonDown];
        };
    }
    else
    {
        __asm {
            pop eax;
            pop ecx;
            xor eax, eax;
            retn 8;
        }
    }
} 


VOID __declspec(naked) CMyMapViewWnd__PostDraw()
{
    __asm {

        push esi;
        mov esi, ecx;

        call [MapUpdate];
        call [MapAttach];

        mov ecx, esi;
        call [CMyMapViewWnd__OldPostDraw];
        push eax;

        call [MapDetach];
        pop eax;
        mov ecx, esi;
        pop esi;
        ret;
    };
}

class CMyMapViewWnd
{
public:
    DWORD Constructor_Trampoline(class CXWnd *);
    DWORD Constructor_Detour(class CXWnd *wnd)
    {
        CMapViewWnd *pWnd=(CMapViewWnd*)this;
        DWORD Ret=Constructor_Trampoline(wnd);
        PCSIDLWNDVFTABLE pvfTable = new CSIDLWNDVFTABLE;
        PCSIDLWNDVFTABLE pMapViewMapVfTable = new CSIDLWNDVFTABLE;
        *pvfTable=*pWnd->pvfTable;
        *pMapViewMapVfTable=*((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable;

        CMyMapViewWnd__OldvfTable=pWnd->pvfTable;
        pWnd->pvfTable=pvfTable;
        MapViewMap_OldvfTable=((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable;
        ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable=pMapViewMapVfTable;
        CMyMapViewWnd__OldPostDraw=(DWORD)((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->PostDraw2;
        CMyMapViewWnd__OldDestructor=(DWORD)pWnd->pvfTable->vector_deleting_destructor;
        pWnd->pvfTable->vector_deleting_destructor=CMyMapViewWnd__Destructor;
        ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->PostDraw2=CMyMapViewWnd__PostDraw;
        MapViewMap__OldHandleRButtonDown=(DWORD)((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->HandleRButtonDown;
        ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->HandleRButtonDown=MapViewMap__HandleRButtonDown;
        return Ret;
    }

    static void StealVFTable()
    {
        if (CMapViewWnd *pWnd=(CMapViewWnd*)pMapViewWnd)
        {
            PCSIDLWNDVFTABLE pvfTable = new CSIDLWNDVFTABLE;
            PCSIDLWNDVFTABLE pMapViewMapVfTable = new CSIDLWNDVFTABLE;
            *pvfTable=*pWnd->pvfTable;
            *pMapViewMapVfTable=*((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable;

            CMyMapViewWnd__OldvfTable=pWnd->pvfTable;
            pWnd->pvfTable=pvfTable;
            MapViewMap_OldvfTable=((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable;
            ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable=pMapViewMapVfTable;
            CMyMapViewWnd__OldPostDraw=(DWORD)((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->PostDraw2;
            CMyMapViewWnd__OldDestructor=(DWORD)pWnd->pvfTable->vector_deleting_destructor;
            pWnd->pvfTable->vector_deleting_destructor=CMyMapViewWnd__Destructor;
            ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->PostDraw2=CMyMapViewWnd__PostDraw;
            MapViewMap__OldHandleRButtonDown=(DWORD)((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->HandleRButtonDown;
            ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable->HandleRButtonDown=MapViewMap__HandleRButtonDown;
        }
    }

    static void RestoreVFTable()
    {
        if (CMapViewWnd *pWnd=(CMapViewWnd*)pMapViewWnd)
        {
            if (CMyMapViewWnd__OldvfTable && MapViewMap_OldvfTable) { 
                delete pWnd->pvfTable;
                pWnd->pvfTable=CMyMapViewWnd__OldvfTable;
                delete ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable;
                ((PEQMAPWINDOW)pWnd)->pMapViewMapVfTable = MapViewMap_OldvfTable;
            }
        }
    }
};

DETOUR_TRAMPOLINE_EMPTY(DWORD CMyMapViewWnd::Constructor_Trampoline(class CXWnd *)); 

bool Update=true;

#ifndef ISXEQ
// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
    DebugSpewAlways("Initializing MQ2Map");

    bmMapRefresh=AddMQ2Benchmark("Map Refresh");
    unsigned long i;
    CHAR szBuffer[MAX_STRING]={0};
    CHAR tmp_1[MAX_STRING] = {0};
    CHAR tmp_2[MAX_STRING] = {0};
    for (i=0;MapFilterOptions[i].szName;i++) {
        sprintf(szBuffer,"%s-Color",MapFilterOptions[i].szName);
        MapFilterOptions[i].Enabled = GetPrivateProfileInt("Map Filters",MapFilterOptions[i].szName,MapFilterOptions[i].Default,INIFileName);
        MapFilterOptions[i].Color = GetPrivateProfileInt("Map Filters",szBuffer,MapFilterOptions[i].DefaultColor,INIFileName) | 0xFF000000;
		sprintf(tmp_1,"%s-Size",MapFilterOptions[i].szName);
		GetPrivateProfileString("Marker Filters",MapFilterOptions[i].szName,"None",tmp_2,MAX_STRING,INIFileName);
		DWORD mark = FindMarker(tmp_2);
		if (mark == 99) mark = 0;
      
		MapFilterOptions[i].Marker = mark;
		MapFilterOptions[i].MarkerSize = GetPrivateProfileInt("Marker Filters",tmp_1,0,INIFileName);
    }
	repeatMapshow = GetPrivateProfileInt("Map Filters","Mapshow-Repeat",FALSE,INIFileName);
	repeatMaphide = GetPrivateProfileInt("Map Filters","Maphide-Repeat",FALSE,INIFileName);

	HighlightSIDELEN = GetPrivateProfileInt("Map Filters", "HighSize", HighlightSIDELEN, INIFileName);
	HighlightPulse = GetPrivateProfileInt("Map Filters", "HighPulse", HighlightPulse, INIFileName);

	GetPrivateProfileString("Map Filters","Mapshow","",mapshowStr,MAX_STRING,INIFileName);
	GetPrivateProfileString("Map Filters","Maphide","",maphideStr,MAX_STRING,INIFileName);
    MapInit();
    GetPrivateProfileString("Naming Schemes","Normal","%N",MapNameString,MAX_STRING,INIFileName);
    GetPrivateProfileString("Naming Schemes","Target","%N",MapTargetNameString,MAX_STRING,INIFileName);

    for (i=1;i<16;i++)
    {
        sprintf(szBuffer,"KeyCombo%d",i);
        GetPrivateProfileString("Right Click",szBuffer,MapSpecialClickString[i],MapSpecialClickString[i],MAX_STRING,INIFileName);
    }

    // Do not use Custom, since the string isn't stored
    MapFilterOptions[MAPFILTER_Custom].Enabled = 0;


    AddCommand("/mapfilter",MapFilters,0,1,1);
    AddCommand("/maphide",MapHideCmd,0,1,1);
    AddCommand("/mapshow",MapShowCmd,0,1,1);
    AddCommand("/highlight",MapHighlightCmd,0,1,1);
    AddCommand("/mapnames",MapNames,0,1,1);
    AddCommand("/mapclick",MapClickCommand,0,1,0);

    EzDetour(CMapViewWnd__CMapViewWnd,&CMyMapViewWnd::Constructor_Detour,&CMyMapViewWnd::Constructor_Trampoline);
    CMyMapViewWnd::StealVFTable();
    AddMQ2Data("MapSpawn",dataMapSpawn);
	ClearSearchSpawn(&MapFilterNamed);
	ParseSearchSpawn("#", &MapFilterNamed);
}

// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
    DebugSpewAlways("Shutting down MQ2Map");
    Update=false;
    RemoveMQ2Data("MapSpawn");

    RemoveDetour(CMapViewWnd__CMapViewWnd);

    MapClear();
    CMyMapViewWnd::RestoreVFTable();

    RemoveMQ2Benchmark(bmMapRefresh);
    RemoveCommand("/maphide");
    RemoveCommand("/mapshow");
    RemoveCommand("/mapfilter");
    RemoveCommand("/highlight");
    RemoveCommand("/mapnames");
    RemoveCommand("/mapclick");
}

// This is called every time MQ pulses
PLUGIN_API VOID OnPulse(VOID)
{
   // DONT leave in this debugspew, even if you leave in all the others
   //   DebugSpewAlways("MQ2Mapshow::OnPulse()");

   long curTime = MakeTime();
   clock_t curClockTime = clock();
   bool cleared = false;

   CHAR szBuffer[MAX_STRING] = {0};

   if (curClockTime > highPulseRepeatLast + highPulseRepeatIntervalMillis && HighlightPulse)
   {
	   if (HighlightPulseIndex == 5 || HighlightPulseIndex == -5)
		   HighlightPulseIncreasing = !HighlightPulseIncreasing;

	   if (HighlightPulseIncreasing)
		   HighlightPulseIndex++;
	   else
		   HighlightPulseIndex--;

	   highPulseRepeatLast = curClockTime;
   }

   if (curTime > repeatLast + repeatInterval) {

      if (repeatMapshow && strlen(mapshowStr) > 0) {
         if (!cleared) {
            MapClear();
            MapGenerate();
            cleared = true;
         }

         SEARCHSPAWN ss;
         ClearSearchSpawn(&ss);
         ParseSearchSpawn(mapshowStr,&ss);
          MapShow(ss);
      }

      if (repeatMaphide && strlen(maphideStr) > 0) {
         if (!cleared) {
            MapClear();
            MapGenerate();
            cleared = true;
         }

         SEARCHSPAWN ss;
         ClearSearchSpawn(&ss);
         ParseSearchSpawn(maphideStr,&ss);
          MapHide(ss);
      }

      repeatLast = curTime;
   }
}

// This is called each time a spawn is added to a zone (inserted into EQ's list of spawns),
// or for each existing spawn when a plugin first initializes
// NOTE: When you zone, these will come BEFORE OnZoned
PLUGIN_API VOID OnAddSpawn(PSPAWNINFO pNewSpawn)
{
    // your toon's spawn id changes and it's no longer zero to start
    // don't added it all 
    if (Update && pNewSpawn->SpawnID != 0 && GetCharInfo()->pSpawn != pNewSpawn) {
        DebugSpewAlways("MQ2Map::OnAddSpawn(%s) = %d",pNewSpawn->Name, pNewSpawn->SpawnID);
        AddSpawn(pNewSpawn);
    }
}

// This is called each time a spawn is removed from a zone (removed from EQ's list of spawns).
// It is NOT called for each existing spawn when a plugin shuts down.
PLUGIN_API VOID OnRemoveSpawn(PSPAWNINFO pSpawn)
{
    DebugSpewAlways("MQ2Map::OnRemoveSpawn(%s) = %d",pSpawn->Name, pSpawn->SpawnID);
    if (Update)
        RemoveSpawn(pSpawn);
}

PLUGIN_API VOID SetGameState(DWORD GameState)
{
    if (GameState==3)
    {
        MapClear();
    }
}

// This is called each time a ground item is added to a zone
// or for each existing ground item when a plugin first initializes
// NOTE: When you zone, these will come BEFORE OnZoned
PLUGIN_API VOID OnAddGroundItem(PGROUNDITEM pNewGroundItem)
{
    DebugSpewAlways("MQ2Map::OnAddGroundItem(%d)",pNewGroundItem->DropID);
    if (Update)
        AddGroundItem(pNewGroundItem);
}

// This is called each time a ground item is removed from a zone
// It is NOT called for each existing ground item when a plugin shuts down.
PLUGIN_API VOID OnRemoveGroundItem(PGROUNDITEM pGroundItem)
{
    DebugSpewAlways("MQ2Map::OnRemoveGroundItem(%d)",pGroundItem->DropID);
    if (Update)
        RemoveGroundItem(pGroundItem);
}

PLUGIN_API  PMAPLINE MQ2MapAddLine() {
   return InitLine();
}

PLUGIN_API VOID MQ2MapDeleteLine(PMAPLINE pLine) {
   DeleteLine(pLine);
} 

#endif
MQ2Map.h

Code: Select all

#include <map>
using namespace std;
#ifdef ISXEQ
#include "ISXEQMap.h"
#endif

#define MAPFILTER_All            0
#define MAPFILTER_PC             1
#define MAPFILTER_PCConColor     2
#define MAPFILTER_Group          3
#define MAPFILTER_Mount          4
#define MAPFILTER_NPC            5
#define MAPFILTER_NPCConColor    6
#define MAPFILTER_Untargetable   7
#define MAPFILTER_Pet            8
#define MAPFILTER_Corpse         9
#define MAPFILTER_Chest          10
#define MAPFILTER_Trigger        11
#define MAPFILTER_Trap           12
#define MAPFILTER_Timer          13
#define MAPFILTER_Ground         14
#define MAPFILTER_Target         15
#define MAPFILTER_TargetLine     16
#define MAPFILTER_TargetRadius   17
#define MAPFILTER_TargetMelee    18
#define MAPFILTER_Vector         19
#define MAPFILTER_Custom         20
#define MAPFILTER_CastRadius     21
#define MAPFILTER_NormalLabels   22
#define MAPFILTER_ContextMenu    23
#define MAPFILTER_SpellRadius    24
#define MAPFILTER_Aura           25
#define MAPFILTER_Object         26
#define MAPFILTER_Banner         27
#define MAPFILTER_Campfire       28
#define MAPFILTER_PCCorpse       29
#define MAPFILTER_NPCCorpse      30
#define MAPFILTER_Mercenary      31
#define MAPFILTER_Named          32
#define MAPFILTER_TargetPath     33
#define MAPFILTER_Marker         34
#define MAPFILTER_NUMBER         35
#define MAPFILTER_Invalid        (-1)
// normal labels



typedef struct _MAPFILTER {
    PCHAR szName;
    //DWORD Index;
    DWORD Default;
    DWORD DefaultColor;
    BOOL bIsToggle;
    DWORD RequiresOption;
    BOOL RegenerateOnChange;
    PCHAR szHelpString;
	DWORD Marker;
	DWORD MarkerSize;
    DWORD Enabled;
    DWORD Color;
} MAPFILTER, *PMAPFILTER;

extern unsigned long bmMapRefresh;

extern DWORD HighlightColor;
extern DWORD HighlightSIDELEN;
extern BOOL HighlightPulse;
extern BOOL HighlightPulseIncreasing;
extern int HighlightPulseIndex;
extern DWORD HighlightPulseDiff;

extern CHAR MapNameString[MAX_STRING];
extern CHAR MapTargetNameString[MAX_STRING];
extern CHAR mapshowStr[MAX_STRING];
extern CHAR maphideStr[MAX_STRING];
extern SEARCHSPAWN MapFilterCustom;
extern SEARCHSPAWN MapFilterNamed;
extern MAPFILTER MapFilterOptions[];
extern CHAR MapSpecialClickString[16][MAX_STRING];
extern BOOL repeatMapshow;
extern BOOL repeatMaphide;

/* COMMANDS */
VOID MapFilters(PSPAWNINFO pChar, PCHAR szLine);
VOID MapFilterSetting(PSPAWNINFO pChar, DWORD nMapFilter, PCHAR szValue=NULL);
VOID MapHighlightCmd(PSPAWNINFO pChar, PCHAR szLine);
VOID PulseReset();
VOID MapHideCmd(PSPAWNINFO pChar, PCHAR szLine);
VOID MapShowCmd(PSPAWNINFO pChar, PCHAR szLine);
VOID MapNames(PSPAWNINFO pChar, PCHAR szLine);
VOID MapClickCommand(PSPAWNINFO pChar, PCHAR szLine);
PCHAR FormatMarker(PCHAR szLine,PCHAR szDest);
DWORD TypeToMapfilter(PSPAWNINFO pChar);


/* API */
VOID MapInit();
VOID MapClear();
VOID MapGenerate();
DWORD MapHighlight(SEARCHSPAWN *pSearch);
DWORD MapHide(SEARCHSPAWN &Search);
DWORD MapShow(SEARCHSPAWN &Search);
VOID MapUpdate();
VOID MapAttach();
VOID MapDetach();

bool MapSelectTarget();
DWORD FindMarker(PCHAR szMark);
long  MakeTime();


#ifndef ISXEQ
BOOL dataMapSpawn(PCHAR szIndex, MQ2TYPEVAR &Ret);
#else
bool dataMapSpawn(int argc, char *argv[], LSTYPEVAR &Ret);
#endif

struct _MAPSPAWN* AddSpawn(PSPAWNINFO pNewSpawn,BOOL ExplicitAllow=false);
bool RemoveSpawn(PSPAWNINFO pSpawn);
void AddGroundItem(PGROUNDITEM pGroundItem);
void RemoveGroundItem(PGROUNDITEM pGroundItem);

static inline BOOL IsOptionEnabled(DWORD Option)
{
    if (Option==MAPFILTER_Invalid)
        return true;
    return (MapFilterOptions[Option].Enabled && IsOptionEnabled(MapFilterOptions[Option].RequiresOption));
}

static inline BOOL RequirementsMet(DWORD Option)
{
    if (Option==MAPFILTER_Invalid)
        return true;
    return (IsOptionEnabled(MapFilterOptions[Option].RequiresOption));
}
PLUGIN_API PMAPLINE InitLine();
PLUGIN_API VOID DeleteLine(PMAPLINE pLine); 

MQ2MapCommands.cpp

Code: Select all

#include "../MQ2Plugin.h"
#include "MQ2Map.h"

#ifndef ISXEQ
// ***************************************************************************
// Function:    MapFilters
// Description: Our '/mapfilter' command
//              Sets map filters
// Usage:       /mapfilter [options|help]
// ***************************************************************************
VOID MapFilterSetting(PSPAWNINFO pChar, DWORD nMapFilter, PCHAR szValue)
{
    CHAR szBuffer[MAX_STRING] = {0};
    CHAR Buff[MAX_STRING]={0};
    DWORD dwValue = 0;
    PCHAR szFilterMap[] = {
        "hide",
        "show",
        NULL
    };
    if (!pChar) return;
    PMAPFILTER pMapFilter=&MapFilterOptions[nMapFilter];
    if (!RequirementsMet(nMapFilter))
    {
        sprintf(szBuffer,"'%s' requires '%s' option.  Please enable this option first.",pMapFilter->szName,MapFilterOptions[pMapFilter->RequiresOption].szName);
        WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
        return;
    }
    if (!szValue) {
        if (pMapFilter->bIsToggle) {
            sprintf(szBuffer,"%s: %s",pMapFilter->szName,szFilterMap[pMapFilter->Enabled]);
        } else if (nMapFilter == MAPFILTER_Custom) {
            if (IsOptionEnabled(nMapFilter)==0) {
                sprintf(szBuffer,"%s: Off",pMapFilter->szName);
            } else {
                sprintf(szBuffer,"%s: %s",pMapFilter->szName,FormatSearchSpawn(Buff,&MapFilterCustom));
            }
        } else {
            sprintf(szBuffer,"%s: %d",pMapFilter->szName,pMapFilter->Enabled);
        }
        if (pMapFilter->DefaultColor != -1) {
            CHAR szBuffer2[MAX_STRING] = {0};
            DWORD R,G,B;
            R= (pMapFilter->Color&0xFF0000)/0x10000;
            G= (pMapFilter->Color&0xFF00)/0x100;
            B= pMapFilter->Color&0xFF;
            sprintf(szBuffer2,"%s (Color: %d %d %d)",szBuffer,R,G,B);
            strcpy(szBuffer,szBuffer2);
        }
    } else {
        if (pMapFilter->bIsToggle) {
            if (!stricmp(szFilterMap[0],szValue)) {
                pMapFilter->Enabled = 0;
            } else if (!stricmp(szFilterMap[1],szValue)) {
                pMapFilter->Enabled = 1;
            } else {
                pMapFilter->Enabled = 1 - pMapFilter->Enabled;
            }
            sprintf(szBuffer,"%s is now set to: %s",pMapFilter->szName,szFilterMap[IsOptionEnabled(nMapFilter)]);
        } else if (nMapFilter == MAPFILTER_Custom) {
            ClearSearchSpawn(&MapFilterCustom);
            if (szValue[0]==0) {
                pMapFilter->Enabled = 0;
                sprintf(szBuffer,"%s is now set to: Off",pMapFilter->szName);
            } else {
                pMapFilter->Enabled = 1;
                ParseSearchSpawn(szValue,&MapFilterCustom);
                sprintf(szBuffer,"%s is now set to: %s",pMapFilter->szName,FormatSearchSpawn(Buff,&MapFilterCustom));
            }
		}
		else if (nMapFilter == MAPFILTER_Marker) {
			CHAR szBuffer2[MAX_STRING] = {0};
			GetArg(szBuffer2,szValue,1);         
			
			if (!stricmp(szFilterMap[0],szValue)) {
				pMapFilter->Enabled = 0;
				sprintf(szBuffer,"%s is now set to: %s",pMapFilter->szName,szFilterMap[IsOptionEnabled(nMapFilter)]);
			}
			else if (!stricmp(szFilterMap[1],szValue)) {
				pMapFilter->Enabled = 1;
				sprintf(szBuffer,"%s is now set to: %s",pMapFilter->szName,szFilterMap[IsOptionEnabled(nMapFilter)]);
			}
			else {
				pMapFilter->Enabled = 1;
				sprintf(szBuffer,"%s %s",pMapFilter->szName,FormatMarker(szValue,Buff));
			}
        }  else {
            pMapFilter->Enabled = atoi(szValue);
            sprintf(szBuffer,"%s is now set to: %d",pMapFilter->szName,pMapFilter->Enabled);
        }
    }
    WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
    if (szValue) {
        itoa(pMapFilter->Enabled,szBuffer,10);
        WritePrivateProfileString("Map Filters",pMapFilter->szName,szBuffer,INIFileName);
    }
}

VOID MapFilters(PSPAWNINFO pChar, PCHAR szLine)
{
    bRunNextCommand = TRUE;
    CHAR szArg[MAX_STRING] = {0};
    GetArg(szArg,szLine,1);
    PCHAR szRest = GetNextArg(szLine);
    CHAR szBuffer[MAX_STRING] = {0};

    // Display settings
    if (szArg[0]==0) {
        WriteChatColor("Map filtering settings:",USERCOLOR_DEFAULT);
        WriteChatColor("-----------------------",USERCOLOR_DEFAULT);
        for (DWORD i=0;MapFilterOptions[i].szName!=NULL;i++) 
            if (RequirementsMet(i))
                MapFilterSetting(pChar,i);

        // Display Help
    } 
    else if (!strnicmp(szArg,"help",4)) 
    {
        WriteChatColor("Map filtering options:",USERCOLOR_DEFAULT);
        for (DWORD i=0;MapFilterOptions[i].szName!=NULL;i++) {
            sprintf(szBuffer,"%s%s: %s",MapFilterOptions[i].szName,(MapFilterOptions[i].bIsToggle)?"":" #",MapFilterOptions[i].szHelpString);
            WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
        }
        WriteChatColor("'option' color [r g b]: Set display color for 'option' (Omit to reset to default)",USERCOLOR_DEFAULT);

        // Set option
    } else {
        PMAPFILTER Found = 0;
        for (DWORD i=0;MapFilterOptions[i].szName!=NULL;i++) {
            if (!stricmp(szArg,MapFilterOptions[i].szName)) {
                if (!strnicmp(szRest,"color",5)) {
                    if (MapFilterOptions[i].DefaultColor == -1) {
                        sprintf(szBuffer,"Option '%s' does not have a color.",MapFilterOptions[i].szName);
                        WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
                    } else {
                        DWORD R,G,B;
                        CHAR szBuffer2[MAX_STRING] = {0};
                        GetArg(szArg,szRest,2);
                        if (szArg[0]==0) {
                            MapFilterOptions[i].Color = MapFilterOptions[i].DefaultColor;
                        } else {
                            R=atoi(szArg);
                            G=atoi(GetArg(szArg,szRest,3));
                            B=atoi(GetArg(szArg,szRest,4));
                            if (R>255) R=255;
                            if (G>255) G=255;
                            if (B>255) B=255;
                            MapFilterOptions[i].Color = R*0x10000 + G*0x100 + B;
                        }
                        sprintf(szBuffer,"Option '%s' color set to: %d %d %d",MapFilterOptions[i].szName,R,G,B);
                        WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
                        itoa(MapFilterOptions[i].Color & 0xFFFFFF,szBuffer,10);
                        sprintf(szBuffer2,"%s-Color",MapFilterOptions[i].szName);
                        WritePrivateProfileString("Map Filters",szBuffer2,szBuffer,INIFileName);
                        MapFilterOptions[i].Color |= 0xFF000000;
                    }
                } else {
                    MapFilterSetting(pChar,i,szRest);
                }
                Found=&MapFilterOptions[i];
            }
        }
        if (!Found) 
            SyntaxError("Usage: /mapfilter [option|help]");
        else if (Found->RegenerateOnChange)
        {
            MapClear();
            MapGenerate();
        }
    }
}


VOID MapHighlightCmd(PSPAWNINFO pChar, PCHAR szLine)
{
    CHAR szArg[MAX_STRING] = {0};
    CHAR szBuffer[MAX_STRING] = {0};
    bRunNextCommand = TRUE;
    if (szLine==0 || szLine[0]==0)
    {
        SyntaxError("Usage: /highlight [reset|spawnfilter|size|pulse|[color # # #]]");
        return;
    };

    GetArg(szArg,szLine,1);
    if (!stricmp(szArg,"color"))
    {
        GetArg(szArg,szLine,2);
        if (szLine[0]==0)
        {
            sprintf(szBuffer,"Highlight color: %d %d %d",(HighlightColor&0x00FF0000)>>16,(HighlightColor&0x0000FF00)>>8,(HighlightColor&0x000000FF));
            WriteChatColor(szBuffer);
            return;
        }
        unsigned char R=atoi(szArg);
        unsigned char G=atoi(GetArg(szArg,szLine,3));
        unsigned char B=atoi(GetArg(szArg,szLine,4));
        HighlightColor=0xFF000000 | (R << 16) | (G << 8) | (B);
        sprintf(szBuffer,"Highlight color: %d %d %d",R,G,B);
        WriteChatColor(szBuffer);
        return;
    }
    else if (!stricmp(szArg,"reset"))
    {
        MapHighlight(0);
        WriteChatColor("Highlighting reset",USERCOLOR_DEFAULT);
        return;
    }
	else if (!stricmp(szArg, "size"))
	{
		HighlightSIDELEN = strtol(GetArg(szArg, szLine, 2), 0, 0);
		PulseReset();
		sprintf(szBuffer, "Highlight size: %d", HighlightSIDELEN);
		WriteChatColor(szBuffer);

		// Write setting to file
		char szTest[5];
		sprintf_s(szTest, "%d", HighlightSIDELEN);
		WritePrivateProfileString("Map Filters", "HighSize", szTest, INIFileName);
		return;
	}
	else if (!stricmp(szArg, "pulse"))
	{
		HighlightPulse = !HighlightPulse;
		PulseReset();
		sprintf(szBuffer, "Highlight pulse: %s", HighlightPulse ? "ON" : "OFF");
		WriteChatColor(szBuffer);

		// Write setting to file
		WritePrivateProfileString("Map Filters", "HighPulse", HighlightPulse ? "1" : "0", INIFileName);
		return;
	}

    if (PCHARINFO pCharInfo=GetCharInfo())
    {
        SEARCHSPAWN ssHighlight;
        ClearSearchSpawn(&ssHighlight);
        ParseSearchSpawn(szLine,&ssHighlight);
        sprintf(szBuffer,"%d mapped spawns highlighted",MapHighlight(&ssHighlight));
        WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
    }
}

VOID PulseReset()
{
	HighlightPulseIncreasing = TRUE;
	HighlightPulseIndex = 0;
	HighlightPulseDiff = HighlightSIDELEN / 10;
}

VOID MapHideCmd(PSPAWNINFO pChar, PCHAR szLine)
{
    CHAR szArg[MAX_STRING] = {0};
    CHAR szBuffer[MAX_STRING] = {0};
    bRunNextCommand = TRUE;
    if (szLine==0 || szLine[0]==0)
    {
        SyntaxError("Usage: /maphide [spawnfilter|reset|repeat]");
        return;
    };
    GetArg(szArg,szLine,1);
    if (!stricmp(szArg,"reset"))
    {
        MapClear();
        MapGenerate();
        WriteChatColor("Map spawns regenerated",USERCOLOR_DEFAULT);
        return;
    }
    if (!stricmp(szArg,"repeat"))
    {
       if (repeatMaphide) 
		   repeatMaphide = FALSE;
		else 
			repeatMaphide = TRUE;
      
        itoa(repeatMaphide,szBuffer,10);
        WritePrivateProfileString("Map Filters","Maphide-Repeat",szBuffer,INIFileName);

		sprintf(szBuffer,"maphide repeat set to: %s",(repeatMaphide ? "on" : "off"));
		WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
		return;
    }
    if (PCHARINFO pCharInfo=GetCharInfo())
    {
        SEARCHSPAWN ssHide;
        ClearSearchSpawn(&ssHide);
        ParseSearchSpawn(szLine,&ssHide);
        sprintf(szBuffer,"%d mapped spawns hidden",MapHide(ssHide));
        WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
    }
}

VOID MapShowCmd(PSPAWNINFO pChar, PCHAR szLine)
{
    CHAR szArg[MAX_STRING] = {0};
    CHAR szBuffer[MAX_STRING] = {0};
    bRunNextCommand = TRUE;
    if (szLine==0 || szLine[0]==0)
    {
        SyntaxError("Usage: /mapshow [spawnfilter|reset|repeat]");
        return;
    };
    GetArg(szArg,szLine,1);
    if (!stricmp(szArg,"reset"))
    {
        MapClear();
        MapGenerate();
        WriteChatColor("Map spawns regenerated");
        return;
    }
    if (!stricmp(szArg,"repeat"))
    {
		if (repeatMapshow) 
			repeatMapshow = FALSE;
		else 
			repeatMapshow = TRUE;

        itoa(repeatMapshow,szBuffer,10);
        WritePrivateProfileString("Map Filters","Mapshow-Repeat",szBuffer,INIFileName);

		sprintf(szBuffer,"mapshow repeat set to: %s",(repeatMapshow ? "on" : "off"));
		WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
		return;
    }
    if (PCHARINFO pCharInfo=GetCharInfo())
    {
        SEARCHSPAWN ssShow;
        ClearSearchSpawn(&ssShow);
        ParseSearchSpawn(szLine,&ssShow);
        sprintf(szBuffer,"%d previously hidden spawns shown",MapShow(ssShow));
        WriteChatColor(szBuffer,USERCOLOR_DEFAULT);
    }
}

VOID MapNames(PSPAWNINFO pChar, PCHAR szLine)
{
    bRunNextCommand = TRUE;
    CHAR szOut[MAX_STRING]={0};
    if (!szLine[0])
    {
        sprintf(szOut,"Normal naming string: %s",MapNameString);
        WriteChatColor(szOut,USERCOLOR_DEFAULT);
        sprintf(szOut,"Target naming string: %s",MapTargetNameString);
        WriteChatColor(szOut,USERCOLOR_DEFAULT);
        return;
    }
    CHAR szArg[MAX_STRING] = {0};
    GetArg(szArg,szLine,1);
    PCHAR szRest = GetNextArg(szLine);
    if (!stricmp(szArg,"target"))
    {
        if (!stricmp(szRest,"reset"))
            strcpy(MapTargetNameString,"%N");
        else
            strcpy(MapTargetNameString,szRest);
        sprintf(szOut,"Target naming string: %s",MapTargetNameString);
        WriteChatColor(szOut,USERCOLOR_DEFAULT);
        WritePrivateProfileString("Naming Schemes","Target",MapTargetNameString,INIFileName);
        MapClear();
        MapGenerate();
    }
    else if (!stricmp(szArg,"normal"))
    {
        if (!stricmp(szRest,"reset"))
            strcpy(MapNameString,"%N");
        else
            strcpy(MapNameString,szRest);
        sprintf(szOut,"Normal naming string: %s",MapNameString);
        WriteChatColor(szOut,USERCOLOR_DEFAULT);
        WritePrivateProfileString("Naming Schemes","Normal",MapNameString,INIFileName);
        MapClear();
        MapGenerate();
    }
    else
    {
        SyntaxError("Usage: /mapnames <target|normal> [value|reset]");
    }
}
#endif

PCHAR DescribeCombo(DWORD Combo)
{
    static char Description[256];
    Description[0]=0;
    int pos=0;
    if (Combo&XKF_SHIFT)
    {
        strcpy(&Description[pos],"shift");
        pos+=5;
    }
    if (Combo&XKF_CTRL)
    {
        if (pos)
        {
            Description[pos]='+';
            pos++;
        }

        strcpy(&Description[pos],"ctrl");
        pos+=4;
    }

    if (Combo&XKF_LALT)
    {
        if (pos)
        {
            Description[pos]='+';
            pos++;
        }

        strcpy(&Description[pos],"lalt");
        pos+=4;
    }

    if (Combo&XKF_RALT)
    {
        if (pos)
        {
            Description[pos]='+';
            pos++;
        }

        strcpy(&Description[pos],"ralt");
    }

    if (!Description[0])
    {
        return "Invalid";
    }

    return &Description[0];
}

DWORD ParseCombo(PCHAR Combo)
{
    DWORD Ret=0;
    if (!Combo || !Combo[0])
        return 0;
    CHAR Copy[MAX_STRING];
    strcpy(Copy,Combo);
    Combo=strtok(Copy,"+");
    while(Combo)
    {
        if (!stricmp(Combo,"ctrl"))
            Ret+=XKF_CTRL;
        else if (!stricmp(Combo,"shift"))
            Ret+=XKF_SHIFT;
        else if (!stricmp(Combo,"lalt"))
            Ret+=XKF_LALT;
        else if (!stricmp(Combo,"ralt"))
            Ret+=XKF_RALT;
        else if (!stricmp(Combo,"alt"))
            Ret+=XKF_LALT;
        Combo=strtok(NULL,"+");
    }
    return Ret;
}
#ifndef ISXEQ
VOID MapClickCommand(PSPAWNINFO pChar, PCHAR szLine)
{
    if (!szLine[0])
    {
        SyntaxError("Usage: /mapclick <list|<key[+key[...]]> <clear|command>>");
        return;
    }
    bRunNextCommand = TRUE;

    CHAR szArg[MAX_STRING] = {0};
    CHAR szBuffer[MAX_STRING] = {0};
    GetArg(szArg,szLine,1);
    PCHAR szRest = GetNextArg(szLine);

    if (!stricmp(szArg,"list"))
    {
        int Count=0;
        for (int i=1 ; i < 16 ; i++)
        {
            if (MapSpecialClickString[i][0])
            {
                sprintf(szBuffer,"%s: %s",DescribeCombo(i),MapSpecialClickString[i]);
                WriteChatColor(szBuffer);
                Count++;
            }
        }
        sprintf(szBuffer,"%d special right-click commands",Count);
        WriteChatColor(szBuffer);
        return;
    }

    DWORD Combo=ParseCombo(szArg);
    if (!Combo)
    {
        sprintf(szBuffer,"Invalid combo '%s'",szArg);
        WriteChatColor(szBuffer);
        return;
    }

    if (!szRest[0])
    {
        sprintf(szBuffer,"%s: %s",DescribeCombo(Combo),MapSpecialClickString[Combo]);
        WriteChatColor(szBuffer);
        return;
    }

    if (!stricmp(szRest,"clear"))
    {

        MapSpecialClickString[Combo][0]=0;

        sprintf(szBuffer,"KeyCombo%d",Combo);
        WritePrivateProfileString("Right Click",szBuffer,MapSpecialClickString[Combo],INIFileName);
        sprintf(szBuffer,"%s cleared",DescribeCombo(Combo));
        WriteChatColor(szBuffer);
        return;
    }

    strcpy(MapSpecialClickString[Combo],szRest);
    sprintf(szBuffer,"KeyCombo%d",Combo);
    WritePrivateProfileString("Right Click",szBuffer,MapSpecialClickString[Combo],INIFileName);
    sprintf(szBuffer,"%s: %s",DescribeCombo(Combo),MapSpecialClickString[Combo]);
    WriteChatColor(szBuffer);
}


#endif

// marker code
PCHAR szMarkType[] = {
    "None",
    "Triangle",
    "Square",
    "Diamond",
	"Ring",
};

PCHAR FormatMarker(PCHAR szLine,PCHAR szDest)
{
    ZeroMemory(szDest,MAX_STRING);

    CHAR MarkType[MAX_STRING] = {0};
    CHAR MarkShape[MAX_STRING] = {0};
    CHAR MarkSize[MAX_STRING] = {0};

    GetArg(MarkType,szLine,1);
    GetArg(MarkShape,szLine,2);
    GetArg(MarkSize,szLine,3);

	if (!strlen(MarkType)) {
		sprintf(szDest,"unchanged, no spawn type given.");
		return szDest;
	}

	if (!strlen(MarkShape)) {
		sprintf(szDest,"unchanged, no shape given.");
		return szDest;
	}

    for (DWORD i = 0; MapFilterOptions[i].szName != NULL; i++) {
        if (!stricmp(MarkType, MapFilterOptions[i].szName)) {

            DWORD Marker = FindMarker(MarkShape);
            if (Marker == 99) {
				sprintf(szDest,"unchanged, unknown shape: '%s'",MarkShape);
                return szDest;
            }

         DWORD Size = 6;
         if (strlen(MarkSize)) {
            Size = (int)atoi(MarkSize);
            if (!Size) {
				sprintf(szDest,"unchanged, invalid size: '%s'",MarkSize);
				return szDest;
				}
            }

         CHAR tmp_1[MAX_STRING] = {0};
         CHAR tmp_2[MAX_STRING] = {0};
         sprintf(tmp_1,"%s-Size",MapFilterOptions[i].szName);
         sprintf(tmp_2,"%d",Size);

         WritePrivateProfileString("Marker Filters",MapFilterOptions[i].szName,szMarkType[Marker],INIFileName);
         WritePrivateProfileString("Marker Filters",tmp_1,tmp_2,INIFileName);

         MapFilterOptions[i].Marker = Marker;
         MapFilterOptions[i].MarkerSize = Size;

         sprintf(szDest,"'%s' is now set to '%s' with size %d.",MapFilterOptions[i].szName,szMarkType[Marker],Size);
         return szDest;
        }
    }

    sprintf(szDest,"unchanged, unknown spawn type: %s",MarkType);
    return szDest;
} 

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Re: Some Map enhancements for /highlight

Post by JudgeD » Sat Dec 26, 2015 8:38 pm

MQ2MapAPI.cpp

Code: Select all

#include "../MQ2Plugin.h"
#include "MQ2Map.h"

#define pMap     ((PEQMAPWINDOW)pMapViewWnd)
typedef struct _MAPSPAWN
{
    PSPAWNINFO pSpawn;
    eSpawnType SpawnType;

    PMAPLABEL pMapLabel;
    PMAPLINE pVector;
    BOOL Highlight;
    BOOL Explicit;
    DWORD Marker;
    DWORD MarkerSize;
    PMAPLINE MarkerLines[10];

    struct _MAPSPAWN *pLast;
    struct _MAPSPAWN *pNext;
} MAPSPAWN, *PMAPSPAWN;

#define FAKESPAWNTYPE 0xFF


PMAPSPAWN pActiveSpawns=0;

PMAPLABEL pLabelList=0;
PMAPLABEL pLabelListTail=0;
PMAPLINE  pLineList=0;
PMAPLINE  pLineListTail=0;



map<unsigned long,PMAPSPAWN> SpawnMap;
map<unsigned long,PMAPSPAWN> GroundItemMap;
map<PMAPLABEL,PMAPSPAWN> LabelMap;

BOOL Update=false;

#define CASTRADIUS_ANGLESIZE 10
PMAPLINE pCastRadius[(360/CASTRADIUS_ANGLESIZE)+1];

PMAPLINE pSpellRadius[(360/CASTRADIUS_ANGLESIZE)+1];

PMAPSPAWN pLastTarget=0;

PMAPLINE pTargetRadius[(360/CASTRADIUS_ANGLESIZE)+1];

PMAPLINE pTargetMelee[(360/CASTRADIUS_ANGLESIZE)+1];

PMAPLINE pTargetLine=0;


inline PMAPLINE InitLine()
{
    PMAPLINE pLine=new MAPLINE;
    pLine->pPrev=0;
    pLine->pNext=pLineList;
    if (pLineList)
        pLineList->pPrev=pLine;
    else
        pLineListTail=pLine;
    pLineList=pLine;
    return pLine;
}

inline void DeleteLine(PMAPLINE pLine)
{
    if (pLine->pNext)
        pLine->pNext->pPrev=pLine->pPrev;
    else
        pLineListTail=pLine->pPrev;
    if (pLine->pPrev)
        pLine->pPrev->pNext=pLine->pNext;
    else
        pLineList=pLine->pNext;
    delete pLine;
}

inline PMAPLABEL InitLabel(PMAPSPAWN pMapSpawn)
{
    PMAPLABEL pLabel=new MAPLABEL;
    pLabel->pPrev=0;
    pLabel->pNext=pLabelList;
    if (pLabelList)
        pLabelList->pPrev=pLabel;
    else
        pLabelListTail=pLabel;
    pLabelList=pLabel;
    LabelMap[pLabel]=pMapSpawn;
    return pLabel;
}

inline void DeleteLabel(PMAPLABEL pLabel)
{
    LabelMap[pLabel]=0;
    if (pLabel->pNext)
        pLabel->pNext->pPrev=pLabel->pPrev;
    else
        pLabelListTail=pLabel->pPrev;
    if (pLabel->pPrev)
        pLabel->pPrev->pNext=pLabel->pNext;
    else
        pLabelList=pLabel->pNext;
    delete pLabel;
}

inline PMAPSPAWN InitSpawn()
{
    PMAPSPAWN pSpawn=new MAPSPAWN;
    pSpawn->pLast=0;
    pSpawn->pNext=pActiveSpawns;
    if (pActiveSpawns)
        pActiveSpawns->pLast=pSpawn;
    pActiveSpawns=pSpawn;
    return pSpawn;    
}

inline void DeleteSpawn(PMAPSPAWN pMapSpawn)
{
    if (pMapSpawn->pNext)
        pMapSpawn->pNext->pLast=pMapSpawn->pLast;
    if (pMapSpawn->pLast)
        pMapSpawn->pLast->pNext=pMapSpawn->pNext;
    else
        pActiveSpawns=pMapSpawn->pNext;
    delete pMapSpawn;
}

void GenerateMarker(PMAPSPAWN pMapSpawn);
PCHAR GenerateSpawnName(PSPAWNINFO pSpawn, PCHAR NameString);
DWORD GetSpawnColor(eSpawnType Type, PSPAWNINFO pSpawn);
PMAPLABEL GenerateLabel(PMAPSPAWN pMapSpawn, DWORD Color);
PMAPLINE GenerateVector(PMAPSPAWN pMapSpawn);
BOOL CanDisplaySpawn(eSpawnType Type, PSPAWNINFO pSpawn);
void RemoveMarker(PMAPSPAWN pMapSpawn);
void MoveMarker(PMAPSPAWN pMapSpawn);

VOID MapInit()
{
    for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
    {
        pCastRadius[i]=0;
        pSpellRadius[i]=0;
        pTargetRadius[i]=0;
        pTargetMelee[i]=0;
    }
}

PMAPSPAWN AddSpawn(PSPAWNINFO pNewSpawn,BOOL ExplicitAllow)
{
   CHAR szBuffer[MAX_STRING] = {0};
    char buf[MAX_STRING] = {0};
    eSpawnType Type=GetSpawnType(pNewSpawn);
    // apply map filter
    if (!ExplicitAllow && !CanDisplaySpawn(Type,pNewSpawn))
        return 0;
    // add spawn to list

    PMAPSPAWN pMapSpawn = InitSpawn();
    if (pNewSpawn->Type!=FAKESPAWNTYPE)
        SpawnMap[pNewSpawn->SpawnID]=pMapSpawn;
    pMapSpawn->SpawnType=Type;
    pMapSpawn->pSpawn=pNewSpawn;
    pMapSpawn->pMapLabel = GenerateLabel(pMapSpawn,GetSpawnColor(Type,pNewSpawn));
    pMapSpawn->Explicit = ExplicitAllow;
    if (IsOptionEnabled(MAPFILTER_Vector))
        pMapSpawn->pVector= GenerateVector(pMapSpawn);
    else
        pMapSpawn->pVector=0;

    pMapSpawn->Highlight=false;

#if 0
    //Debugging
    if (Type == SPAWN_CORPSE || Type == ITEM )
    {
        sprintf(buf, "AddSpawn(Corpse or Item): Name: %s, Type: %d, BodyType: %d",
            pMapSpawn->pSpawn->Name, pMapSpawn->pSpawn->Type, GetBodyType(pMapSpawn->pSpawn) );
        DebugSpew(buf);
    }
#endif

   // new stuff for Marker changes
    if (IsOptionEnabled(MAPFILTER_Marker)) {
		pMapSpawn->Marker = MapFilterOptions[TypeToMapfilter(pNewSpawn)].Marker;
		pMapSpawn->MarkerSize = MapFilterOptions[TypeToMapfilter(pNewSpawn)].MarkerSize;

        GenerateMarker(pMapSpawn);
        MoveMarker(pMapSpawn);
    } else if (!IsOptionEnabled(MAPFILTER_Marker)) {
		if (pMapSpawn->Marker!=0)
            pMapSpawn->Marker = 0;
    }
    return pMapSpawn;
}

void RemoveSpawn(PMAPSPAWN pMapSpawn)
{
    free(pMapSpawn->pMapLabel->Label);
    DeleteLabel(pMapSpawn->pMapLabel);

    if (pMapSpawn->pVector)
    {
        DeleteLine(pMapSpawn->pVector);
        pMapSpawn->pVector=0;
    }

   if (pMapSpawn->Marker)
      RemoveMarker(pMapSpawn);
    if (pMapSpawn->pSpawn->Type==FAKESPAWNTYPE)
        delete pMapSpawn->pSpawn;
    else
        SpawnMap[pMapSpawn->pSpawn->SpawnID]=0;

    if (pMapSpawn==pLastTarget)
        pLastTarget=0;
    DeleteSpawn(pMapSpawn);
}

bool RemoveSpawn(PSPAWNINFO pSpawn)
{
    PMAPSPAWN pMapSpawn=SpawnMap[pSpawn->SpawnID];
    if (pMapSpawn)
    {
        RemoveSpawn(pMapSpawn);
        return true;
    }
    return false;
}

void AddGroundItem(PGROUNDITEM pGroundItem)
{
    PSPAWNINFO pFakeSpawn=new SPAWNINFO;
    memset(pFakeSpawn,0,sizeof(SPAWNINFO));
    GetFriendlyNameForGroundItem(pGroundItem,pFakeSpawn->Name);
    pFakeSpawn->X = pGroundItem->X;
    pFakeSpawn->Y = pGroundItem->Y;
    pFakeSpawn->Z = pGroundItem->Z;

    pFakeSpawn->HPCurrent = 1;
    pFakeSpawn->HPMax = 1;
    pFakeSpawn->Heading=pGroundItem->Heading;
    pFakeSpawn->Race = pGroundItem->DropID;

    pFakeSpawn->Type=FAKESPAWNTYPE;
    PMAPSPAWN pMapSpawn=AddSpawn(pFakeSpawn);
    if (pMapSpawn)
        GroundItemMap[pGroundItem->DropID]=pMapSpawn;
    else
        delete pFakeSpawn;
}

void RemoveGroundItem(PGROUNDITEM pGroundItem)
{
    PMAPSPAWN pMapSpawn=GroundItemMap[pGroundItem->DropID];
    if (pMapSpawn)
    {
        GroundItemMap[pGroundItem->DropID]=0;
        RemoveSpawn(pMapSpawn);
    }
}


void MapGenerate()
{
    if (!IsOptionEnabled(MAPFILTER_All))
        return;
    PSPAWNINFO pSpawn=(PSPAWNINFO)pSpawnList;
    while(pSpawn)
    {
        AddSpawn(pSpawn);
        pSpawn=pSpawn->pNext;
    }    
    if (!IsOptionEnabled(MAPFILTER_Ground))
        return;
    PGROUNDITEM pItem=*(PGROUNDITEM*)pItemList;
    while(pItem)
    {
        AddGroundItem(pItem);
        pItem=pItem->pNext;
    }    
}

void MapClear()
{
    GroundItemMap.clear();
    SpawnMap.clear();


    while(pActiveSpawns) 
    {
        PMAPSPAWN pNextActive=pActiveSpawns->pNext;

        PMAPLABEL pLabel=pActiveSpawns->pMapLabel;
        DebugTry(free(pLabel->Label));
        DeleteLabel(pLabel);

        if (pActiveSpawns->pVector)
        {
            DeleteLine(pActiveSpawns->pVector);
            pActiveSpawns->pVector=0;
        }

		if (pActiveSpawns->Marker)
			RemoveMarker(pActiveSpawns);     
        if (pActiveSpawns->pSpawn->Type==FAKESPAWNTYPE) // fake!
        {
            delete pActiveSpawns->pSpawn;
        }

        DeleteSpawn(pActiveSpawns);
        pActiveSpawns=pNextActive;
    }

    pLastTarget=0;

    if (pTargetLine)
    {
        DeleteLine(pTargetLine);
        pTargetLine=0;
    }

    if (pCastRadius[0])
    {
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
        {
            DeleteLine(pCastRadius[i]);
            pCastRadius[i]=0;
        }
    }
    if (pSpellRadius[0])
    {
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
        {
            DeleteLine(pSpellRadius[i]);
            pSpellRadius[i]=0;
        }
    }
    if (pTargetRadius[0])
    {
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
        {
            DeleteLine(pTargetRadius[i]);
            pTargetRadius[i]=0;
        }
    }
    if (pTargetMelee[0])
    {
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
        {
            DeleteLine(pTargetMelee[i]);
            pTargetMelee[i]=0;
        }
    }
}

void MapUpdate()
{
    char buf[MAX_STRING] = {0};
    PCHARINFO pCharInfo=GetCharInfo();
    if (!pCharInfo)
        return;
    EnterMQ2Benchmark(bmMapRefresh);
    eSpawnType Type;
    PMAPSPAWN pMapSpawn;
    PMAPSPAWN pOldLastTarget = NULL; 
    bool bTargetChanged = false; 

    pOldLastTarget = pLastTarget; 
    if (pLastTarget && pLastTarget->pSpawn!=(PSPAWNINFO)pTarget)
    {
        if (pLastTarget->pSpawn==&EnviroTarget || !CanDisplaySpawn(pLastTarget->SpawnType,pLastTarget->pSpawn))
        {
            RemoveSpawn(pLastTarget);
        }
        pLastTarget=0;
        bTargetChanged=true;
    }

    if (pTarget && IsOptionEnabled(MAPFILTER_Target))
    {
        pLastTarget=SpawnMap[((PSPAWNINFO)pTarget)->SpawnID];
        if (!pLastTarget)
        {
            pLastTarget=AddSpawn((PSPAWNINFO)pTarget);
        }
    }

    pMapSpawn=pActiveSpawns;

    while(pMapSpawn)
    {
#if 0
        // Debugging
        DWORD BodyType=GetBodyType(pMapSpawn->pSpawn);
        if ( pMapSpawn->pSpawn->Type == SPAWN_PLAYER )
        {
            if ( BodyType != 1 )
            {
                sprintf(buf, "MapUpdate: Name: %s, Type: %d, BodyType: %d",
                    pMapSpawn->pSpawn->Name, pMapSpawn->pSpawn->Type, BodyType );
                DebugSpew(buf);
            }
        }
        else if ( pMapSpawn->pSpawn->Type == SPAWN_NPC )
        {
            if ( BodyType != 1 && BodyType != 11 &&
                BodyType != 33 && BodyType != 65 &&
                BodyType != 66 && BodyType != 67 &&
                BodyType != 21 && BodyType != 23 &&
                BodyType != 34 && BodyType != 3  &&
                BodyType != 24 )
            {
                sprintf(buf, "MapUpdate: Name: %s, Type: %d, BodyType: %d",
                    pMapSpawn->pSpawn->Name, pMapSpawn->pSpawn->Type, BodyType );
                DebugSpew(buf);
            }
        }
        else 
        {
            sprintf(buf, "MapUpdate: Name: %s, Type: %d, BodyType: %d",
                pMapSpawn->pSpawn->Name, pMapSpawn->pSpawn->Type, BodyType );
            DebugSpew(buf);
        }

        //End Debugging
#endif

        //Starting New Checks
        if (!pMapSpawn->Explicit && !CanDisplaySpawn(GetSpawnType(pMapSpawn->pSpawn),pMapSpawn->pSpawn)) 
        {
            PMAPSPAWN pNext=pMapSpawn->pNext;
            RemoveSpawn(pMapSpawn);
            pMapSpawn=pNext;
            continue;
        }
        //End New Checks

        pMapSpawn->pMapLabel->Location.X = -pMapSpawn->pSpawn->X;
        pMapSpawn->pMapLabel->Location.Y = -pMapSpawn->pSpawn->Y;
        pMapSpawn->pMapLabel->Location.Z = pMapSpawn->pSpawn->Z;

        if (pMapSpawn->Highlight)
        {
            pMapSpawn->pMapLabel->Color.ARGB=HighlightColor;
        }
        else
        {
            Type=GetSpawnType(pMapSpawn->pSpawn);
            if (Type!=pMapSpawn->SpawnType || ((pMapSpawn==pOldLastTarget) && bTargetChanged))
            {
                if (!CanDisplaySpawn(Type,pMapSpawn->pSpawn))
                {
                    PMAPSPAWN pNext=pMapSpawn->pNext;
                    RemoveSpawn(pMapSpawn);
                    pMapSpawn=pNext;
                    continue;
                }

                pMapSpawn->SpawnType=Type;
                free(pMapSpawn->pMapLabel->Label);
                pMapSpawn->pMapLabel->Label=GenerateSpawnName(pMapSpawn->pSpawn,MapNameString);

            }
            pMapSpawn->pMapLabel->Color.ARGB=GetSpawnColor(pMapSpawn->SpawnType,pMapSpawn->pSpawn);
        }

        if (pMapSpawn->pVector)
        {
            if (pMapSpawn->pSpawn->SpeedRun>0) {
                pMapSpawn->pVector->Start.X = -pMapSpawn->pSpawn->X;
                pMapSpawn->pVector->Start.Y = -pMapSpawn->pSpawn->Y;
                pMapSpawn->pVector->Start.Z = pMapSpawn->pSpawn->Z;
                pMapSpawn->pVector->End.X = -pMapSpawn->pSpawn->X-pMapSpawn->pSpawn->SpeedX*4;
                pMapSpawn->pVector->End.Y = -pMapSpawn->pSpawn->Y-pMapSpawn->pSpawn->SpeedY*4;
                pMapSpawn->pVector->End.Z = pMapSpawn->pSpawn->Z+pMapSpawn->pSpawn->SpeedZ*4;
            } else {
                pMapSpawn->pVector->Start.X = -pMapSpawn->pSpawn->X;
                pMapSpawn->pVector->Start.Y = -pMapSpawn->pSpawn->Y;
                pMapSpawn->pVector->Start.Z = pMapSpawn->pSpawn->Z;
                pMapSpawn->pVector->End.X =-pMapSpawn->pSpawn->X-sinf(pMapSpawn->pSpawn->Heading/256.0f*(FLOAT)PI)*4;
                pMapSpawn->pVector->End.Y =-pMapSpawn->pSpawn->Y-cosf(pMapSpawn->pSpawn->Heading/256.0f*(FLOAT)PI)*4;
                pMapSpawn->pVector->End.Z =pMapSpawn->pSpawn->Z;
            }
        }

       if (IsOptionEnabled(MAPFILTER_Marker))
          MoveMarker(pMapSpawn);
       else if (!IsOptionEnabled(MAPFILTER_Marker))
          RemoveMarker(pMapSpawn);
        pMapSpawn=pMapSpawn->pNext;
    }

    if (IsOptionEnabled(MAPFILTER_CastRadius))
    {
        unsigned long Angle=0;
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++,Angle+=CASTRADIUS_ANGLESIZE)
        {
            if (!pCastRadius[i])
            {
                pCastRadius[i]=InitLine();
                pCastRadius[i]->Layer=3;
            }

            pCastRadius[i]->Color.ARGB=MapFilterOptions[MAPFILTER_CastRadius].Color;
            pCastRadius[i]->Start.Z=pCharInfo->pSpawn->Z;
            pCastRadius[i]->End.Z=pCharInfo->pSpawn->Z;
            pCastRadius[i]->Start.X=-pCharInfo->pSpawn->X + (FLOAT)MapFilterOptions[MAPFILTER_CastRadius].Enabled*cosf((FLOAT)Angle/180.0f*(FLOAT)PI);
            pCastRadius[i]->Start.Y=-pCharInfo->pSpawn->Y + (FLOAT)MapFilterOptions[MAPFILTER_CastRadius].Enabled*sinf((FLOAT)Angle/180.0f*(FLOAT)PI);;
            pCastRadius[i]->End.X=-pCharInfo->pSpawn->X + (FLOAT)MapFilterOptions[MAPFILTER_CastRadius].Enabled*cosf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
            pCastRadius[i]->End.Y=-pCharInfo->pSpawn->Y + (FLOAT)MapFilterOptions[MAPFILTER_CastRadius].Enabled*sinf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
        }
    }
    else if (pCastRadius[0])
    {
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
        {
            DeleteLine(pCastRadius[i]);
            pCastRadius[i]=0;
        }
    }

    if (IsOptionEnabled(MAPFILTER_SpellRadius))
    {
        unsigned long Angle=0;
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++,Angle+=CASTRADIUS_ANGLESIZE)
        {
            if (!pSpellRadius[i])
            {
                pSpellRadius[i]=InitLine();
                pSpellRadius[i]->Layer=3;
            }

            pSpellRadius[i]->Color.ARGB=MapFilterOptions[MAPFILTER_SpellRadius].Color;
            pSpellRadius[i]->Start.Z=pCharInfo->pSpawn->Z;
            pSpellRadius[i]->End.Z=pCharInfo->pSpawn->Z;
            pSpellRadius[i]->Start.X=-pCharInfo->pSpawn->X + (FLOAT)MapFilterOptions[MAPFILTER_SpellRadius].Enabled*cosf((FLOAT)Angle/180.0f*(FLOAT)PI);
            pSpellRadius[i]->Start.Y=-pCharInfo->pSpawn->Y + (FLOAT)MapFilterOptions[MAPFILTER_SpellRadius].Enabled*sinf((FLOAT)Angle/180.0f*(FLOAT)PI);;
            pSpellRadius[i]->End.X=-pCharInfo->pSpawn->X + (FLOAT)MapFilterOptions[MAPFILTER_SpellRadius].Enabled*cosf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
            pSpellRadius[i]->End.Y=-pCharInfo->pSpawn->Y + (FLOAT)MapFilterOptions[MAPFILTER_SpellRadius].Enabled*sinf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
        }
    }
    else if (pSpellRadius[0])
    {
        for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
        {
            DeleteLine(pSpellRadius[i]);
            pSpellRadius[i]=0;
        }
    }

    if (IsOptionEnabled(MAPFILTER_Group))
    {
        PCHARINFO pChar=GetCharInfo();
        for (unsigned long i=1; i<6; i++)
        {
            if (pChar->pGroupInfo && pChar->pGroupInfo->pMember[i])
            {
                CHAR Name[MAX_STRING]={0};
                GetCXStr(pChar->pGroupInfo->pMember[i]->pName,Name,MAX_STRING);
                PSPAWNINFO pSpawn=(PSPAWNINFO)GetSpawnByName(Name);
                if (pSpawn)
                    if (pMapSpawn=SpawnMap[pSpawn->SpawnID])
                    {
                        pMapSpawn->pMapLabel->Color.ARGB=MapFilterOptions[MAPFILTER_Group].Color;
                    }
            }
        }
    }

    if (pLastTarget)
    {
        pLastTarget->pMapLabel->Color.ARGB=MapFilterOptions[MAPFILTER_Target].Color;
        free(pLastTarget->pMapLabel->Label);
        pLastTarget->pMapLabel->Label=GenerateSpawnName(pLastTarget->pSpawn,MapTargetNameString);            

        if (IsOptionEnabled(MAPFILTER_TargetLine))
        {
            if (!pTargetLine)
            {
                pTargetLine=InitLine();
                pTargetLine->Layer=3;
            }
            pTargetLine->Color.ARGB=MapFilterOptions[MAPFILTER_Target].Color;
            pTargetLine->Start.X=-pCharInfo->pSpawn->X;
            pTargetLine->Start.Y=-pCharInfo->pSpawn->Y;
            pTargetLine->Start.Z=pCharInfo->pSpawn->Z;

            pTargetLine->End.X=-((PSPAWNINFO)pTarget)->X;
            pTargetLine->End.Y=-((PSPAWNINFO)pTarget)->Y;
            pTargetLine->End.Z=((PSPAWNINFO)pTarget)->Z;
        }
        else if (pTargetLine)
        {
            DeleteLine(pTargetLine);
            pTargetLine=0;
        }

        if (IsOptionEnabled(MAPFILTER_TargetRadius))
        {
            unsigned long Angle=0;
            for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++,Angle+=CASTRADIUS_ANGLESIZE)
            {
                if (!pTargetRadius[i])
                {
                    pTargetRadius[i]=InitLine();
                    pTargetRadius[i]->Layer=3;
                }

                pTargetRadius[i]->Color.ARGB=MapFilterOptions[MAPFILTER_TargetRadius].Color;
                pTargetRadius[i]->Start.Z=((PSPAWNINFO)pTarget)->Z;
                pTargetRadius[i]->End.Z=((PSPAWNINFO)pTarget)->Z;
                pTargetRadius[i]->Start.X=-((PSPAWNINFO)pTarget)->X + (FLOAT)MapFilterOptions[MAPFILTER_TargetRadius].Enabled*cosf((FLOAT)Angle/180.0f*(FLOAT)PI);
                pTargetRadius[i]->Start.Y=-((PSPAWNINFO)pTarget)->Y + (FLOAT)MapFilterOptions[MAPFILTER_TargetRadius].Enabled*sinf((FLOAT)Angle/180.0f*(FLOAT)PI);;
                pTargetRadius[i]->End.X=-((PSPAWNINFO)pTarget)->X + (FLOAT)MapFilterOptions[MAPFILTER_TargetRadius].Enabled*cosf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
                pTargetRadius[i]->End.Y=-((PSPAWNINFO)pTarget)->Y + (FLOAT)MapFilterOptions[MAPFILTER_TargetRadius].Enabled*sinf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
            }
        }
        else if (pTargetRadius[0])
        {
            for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
            {
                DeleteLine(pTargetRadius[i]);
                pTargetRadius[i]=0;
            }
        }

        if (IsOptionEnabled(MAPFILTER_TargetMelee))
        {
            unsigned long Angle=0;
            for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++,Angle+=CASTRADIUS_ANGLESIZE)
            {
                if (!pTargetMelee[i])
                {
                    pTargetMelee[i]=InitLine();
                    pTargetMelee[i]->Layer=3;
                }

                pTargetMelee[i]->Color.ARGB=MapFilterOptions[MAPFILTER_TargetMelee].Color;
                pTargetMelee[i]->Start.Z=((PSPAWNINFO)pTarget)->Z;
                pTargetMelee[i]->End.Z=((PSPAWNINFO)pTarget)->Z;
                FLOAT MaxMelee;
                if (MapFilterOptions[MAPFILTER_TargetMelee].Enabled==1)
                    MaxMelee=get_melee_range(pLocalPlayer,pTarget); 
                else
                    MaxMelee=get_melee_range(pTarget,pTarget);
                pTargetMelee[i]->Start.X=-((PSPAWNINFO)pTarget)->X + MaxMelee*cosf((FLOAT)Angle/180.0f*(FLOAT)PI);
                pTargetMelee[i]->Start.Y=-((PSPAWNINFO)pTarget)->Y + MaxMelee*sinf((FLOAT)Angle/180.0f*(FLOAT)PI);;
                pTargetMelee[i]->End.X=-((PSPAWNINFO)pTarget)->X + MaxMelee*cosf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
                pTargetMelee[i]->End.Y=-((PSPAWNINFO)pTarget)->Y + MaxMelee*sinf((FLOAT)(Angle+CASTRADIUS_ANGLESIZE)/180.0f*(FLOAT)PI);
            }
        }
        else if (pTargetMelee[0])
        {
            for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
            {
                DeleteLine(pTargetMelee[i]);
                pTargetMelee[i]=0;
            }
        }
    }
    else
    {
        if (pTargetRadius[0])
        {
            for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
            {
                DeleteLine(pTargetRadius[i]);
                pTargetRadius[i]=0;
            }
        }

        if (pTargetMelee[0])
        {
            for (unsigned long i = 0 ; i < (360/CASTRADIUS_ANGLESIZE) ; i++)
            {
                DeleteLine(pTargetMelee[i]);
                pTargetMelee[i]=0;
            }
        }

        if (pTargetLine)
        {
            DeleteLine(pTargetLine);
            pTargetLine=0;
        }
    }
    ExitMQ2Benchmark(bmMapRefresh);



}


PMAPLABEL pActualLineList=0;
void MapAttach()
{
    if (pLabelList)
    {
        pActualLineList=pMap->pLabels;
        if (IsOptionEnabled(MAPFILTER_NormalLabels))
            pLabelListTail->pNext=pMap->pLabels;
        pMap->pLabels=pLabelList;
    }

    if (pLineList)
    {
        pLineListTail->pNext=pMap->pLines;
        pMap->pLines=pLineList;
    }
}

void MapDetach()
{
    if (pLabelList)
    {
        pMap->pLabels=pActualLineList;
        pLabelListTail->pNext=0;
    }
    if (pLineList)
    {
        pMap->pLines=pLineListTail->pNext;
        pLineListTail->pNext=0;
    }
}

bool MapSelectTarget()
{
    if (!pCurrentMapLabel)
        return false;
    PMAPSPAWN pMapSpawn=LabelMap[pCurrentMapLabel];
    if (!pMapSpawn)
        return true;
    if (pMapSpawn->SpawnType==ITEM)
    {
        EnviroTarget=*pMapSpawn->pSpawn;
        EnviroTarget.Type = SPAWN_NPC;
        //EnviroTarget.SpawnID=2999;
        //pTarget = (EQPlayer*)&EnviroTarget;                 
    }
    else
    {
        DWORD Flags=pWndMgr->GetKeyboardFlags();
        PCHARINFO pCharInfo=GetCharInfo();
        if (pCharInfo && Flags && MapSpecialClickString[Flags][0])
        {
            PCHAR Cmd=GenerateSpawnName(pMapSpawn->pSpawn,MapSpecialClickString[Flags]);
#ifndef ISXEQ
            DoCommand(pCharInfo->pSpawn,Cmd);
#else
            pISInterface->ExecuteCommand(Cmd);
#endif
            free(Cmd);
        }
        else
        {
            pTarget=(EQPlayer*)pMapSpawn->pSpawn;
        }
    }
    if(IsOptionEnabled(MAPFILTER_TargetPath))
        return true;
    return false;
}

DWORD MapHighlight(SEARCHSPAWN *pSearch)
{
    if (!pSearch)
    {
        PMAPSPAWN pMapSpawn=pActiveSpawns;
        while(pMapSpawn)
        {
            pMapSpawn->Highlight=false;
            pMapSpawn=pMapSpawn->pNext;
        }
        return 0;
    }
    else
    {
        PCHARINFO pCharInfo=GetCharInfo();
        if (!pCharInfo)
            return 0;
        PMAPSPAWN pMapSpawn=pActiveSpawns;
        unsigned long Count=0;
        while(pMapSpawn)
        {
            // update!
            if (SpawnMatchesSearch(pSearch,pCharInfo->pSpawn,pMapSpawn->pSpawn))
            {
                pMapSpawn->Highlight=true;
                Count++;
            }

            pMapSpawn=pMapSpawn->pNext;
        }
        return Count;
    }
}

PCHAR GenerateSpawnName(PSPAWNINFO pSpawn, PCHAR NameString)
{
    CHAR Name[MAX_STRING]={0};
    unsigned long outpos=0;
#define AddString(str) {strcpy(&Name[outpos],str);outpos+=strlen(&Name[outpos]);}
#define AddInt(yourint) {_itoa(yourint,&Name[outpos],10);outpos+=strlen(&Name[outpos]);}
#define AddFloat10th(yourfloat) {outpos+=sprintf(&Name[outpos],"%.1f",yourfloat);}
    for (unsigned long N = 0 ; NameString[N] ; N++)
    {
        if (NameString[N]=='%')
        {
            N++;
            switch(NameString[N])
            {
            case 'N':// cleaned up name
                strcpy(&Name[outpos],pSpawn->Name);
                CleanupName(&Name[outpos],FALSE);
                outpos+=strlen(&Name[outpos]);
                break;
            case 'n':// original name
                AddString(pSpawn->Name);
                break;
            case 'h':// current health %
                AddInt(pSpawn->HPCurrent);
                break;
            case 'i':
                AddInt(pSpawn->SpawnID);
                break;
            case 'x':
                AddFloat10th(pSpawn->X);
                break;
            case 'y':
                AddFloat10th(pSpawn->Y);
                break;
            case 'z':
                AddFloat10th(pSpawn->Z);
                break;
            case 'R':
                AddString(pEverQuest->GetRaceDesc(pSpawn->Race));
                break;
            case 'C':
                AddString(GetClassDesc(pSpawn->Class));
                break;
            case 'c':
                AddString(pEverQuest->GetClassThreeLetterCode(pSpawn->Class));
                break;
            case 'l':
                AddInt(pSpawn->Level);
                break;
            case '%':
                Name[outpos++]=NameString[N];
                break;
            }
        }
        else
            Name[outpos++]=NameString[N];
    }
    Name[outpos]=0;

    PCHAR ret=(PCHAR)malloc(strlen(Name)+1);
    strcpy(ret,Name);
    return ret;
}

DWORD TypeToMapfilter(PSPAWNINFO pNewSpawn)
{
   eSpawnType Type = GetSpawnType(pNewSpawn);

    switch(Type)
    {
    case PC:
       return MAPFILTER_PC;
    case NPC:
      if (IsOptionEnabled(MAPFILTER_Named)) {
         if (PCHARINFO pCharInfo=GetCharInfo()) {
            if (SpawnMatchesSearch(&MapFilterNamed,pCharInfo->pSpawn,pNewSpawn)) {
               return MAPFILTER_Named;
            }
         }
      }

       return MAPFILTER_NPC;
    case CORPSE:
       return MAPFILTER_Corpse;
    case ITEM:
       return MAPFILTER_Ground;
    case UNTARGETABLE:
       return MAPFILTER_Untargetable;
    case TIMER:
       return MAPFILTER_Timer;
    case TRAP:
       return MAPFILTER_Trap;
    case TRIGGER:
       return MAPFILTER_Trigger;
    case CHEST:
       return MAPFILTER_Chest;
    case PET:
       return MAPFILTER_Pet;
    case MOUNT:
       return MAPFILTER_Mount;
    case AURA:
       return MAPFILTER_Aura;
    case OBJECT:
       return MAPFILTER_Object;
    case BANNER:
       return MAPFILTER_Banner;
    }

    return MAPFILTER_Invalid;
}
BOOL CanDisplaySpawn(eSpawnType Type, PSPAWNINFO pSpawn)
{
    if (!pSpawn)
        return FALSE;

    if ((pSpawn==(PSPAWNINFO)pTarget) && IsOptionEnabled(MAPFILTER_Target))
    {
        return TRUE;
    }
    if (IsOptionEnabled(MAPFILTER_Custom))
    {
        if (PCHARINFO pCharInfo=GetCharInfo())
            return SpawnMatchesSearch(&MapFilterCustom,pCharInfo->pSpawn,pSpawn);
    }
    switch(Type)
    {
    case PC:
        return IsOptionEnabled(MAPFILTER_PC);
    case NPC:
        if (IsOptionEnabled(MAPFILTER_Named))
            return IsNamed(pSpawn);
        else
            return IsOptionEnabled(MAPFILTER_NPC);
    case CORPSE:
        if(pSpawn->Deity == 0)
            return (IsOptionEnabled(MAPFILTER_NPCCorpse) && IsOptionEnabled(MAPFILTER_Corpse));
        else
            return (IsOptionEnabled(MAPFILTER_PCCorpse) && IsOptionEnabled(MAPFILTER_Corpse));
    case ITEM:
        return IsOptionEnabled(MAPFILTER_Ground);
    case UNTARGETABLE:
        return IsOptionEnabled(MAPFILTER_Untargetable);
    case TIMER:
        return IsOptionEnabled(MAPFILTER_Timer);
    case TRAP:
        return IsOptionEnabled(MAPFILTER_Trap);
    case TRIGGER:
        return IsOptionEnabled(MAPFILTER_Trigger);
    case CHEST:
        return IsOptionEnabled(MAPFILTER_Chest);
    case PET:
        return IsOptionEnabled(MAPFILTER_Pet);
    case MOUNT:
        return IsOptionEnabled(MAPFILTER_Mount);
    case AURA:
        return IsOptionEnabled(MAPFILTER_Aura);
    case OBJECT:
        return IsOptionEnabled(MAPFILTER_Object);
    case BANNER:
        return IsOptionEnabled(MAPFILTER_Banner);
    case CAMPFIRE:
        return IsOptionEnabled(MAPFILTER_Campfire);
    case MERCENARY:
        return IsOptionEnabled(MAPFILTER_Mercenary);
    case FLYER:
        return FALSE; // they have no location data, no use trying to display them
    }
    return TRUE;
}

inline DWORD GetSpawnColor(eSpawnType Type, PSPAWNINFO pSpawn)
{
    PCHARINFO pChar=GetCharInfo();
    if (!pChar)
        return 0;

    switch(Type)
    {
    case PC:
        if (IsOptionEnabled(MAPFILTER_PCConColor))
            return ConColorToARGB(ConColor(pSpawn));
        return MapFilterOptions[MAPFILTER_PC].Color;
    case NPC:
        if (IsOptionEnabled(MAPFILTER_NPCConColor))
            return ConColorToARGB(ConColor(pSpawn));
        return MapFilterOptions[MAPFILTER_NPC].Color;
    case CORPSE:
        if(pSpawn->Deity == 0)
            return MapFilterOptions[MAPFILTER_NPCCorpse].Color;
        else
            return MapFilterOptions[MAPFILTER_PCCorpse].Color;
    case UNTARGETABLE:
        return MapFilterOptions[MAPFILTER_Untargetable].Color;
    case CHEST:
        return MapFilterOptions[MAPFILTER_Chest].Color;
    case TRIGGER:
        return MapFilterOptions[MAPFILTER_Trigger].Color;
    case TIMER:
        return MapFilterOptions[MAPFILTER_Timer].Color;
    case TRAP:
        return MapFilterOptions[MAPFILTER_Trap].Color;
    case ITEM:
        return MapFilterOptions[MAPFILTER_Ground].Color;
    case MOUNT:
        return MapFilterOptions[MAPFILTER_Mount].Color;
    case PET:
        return MapFilterOptions[MAPFILTER_Pet].Color;
    case AURA:
        return MapFilterOptions[MAPFILTER_Aura].Color;
    case OBJECT:
        return MapFilterOptions[MAPFILTER_Object].Color;
    case BANNER:
        return MapFilterOptions[MAPFILTER_Banner].Color;
    case CAMPFIRE:
        return MapFilterOptions[MAPFILTER_Campfire].Color;
    case MERCENARY:
        return MapFilterOptions[MAPFILTER_Mercenary].Color;
    }
    return 0;
}

PMAPLABEL GenerateLabel(PMAPSPAWN pMapSpawn, DWORD Color)
{
    PMAPLABEL pLabel=InitLabel(pMapSpawn);
    pLabel->Location.X = -pMapSpawn->pSpawn->X;
    pLabel->Location.Y = -pMapSpawn->pSpawn->Y;
    pLabel->Location.Z = pMapSpawn->pSpawn->Z;
    pLabel->Layer = 3;
    pLabel->Size = 3;
    pLabel->Label = GenerateSpawnName(pMapSpawn->pSpawn,MapNameString);
    pLabel->Color.ARGB = Color;
    pLabel->Width = 20;
    pLabel->Height= 14;
    pLabel->unk_0x2c = 0;
    pLabel->unk_0x30 = 0;
    return pLabel;
}

PMAPLINE GenerateVector(PMAPSPAWN pMapSpawn)
{

    PMAPLINE pNewLine = InitLine();

    if (pMapSpawn->pSpawn->SpeedRun>0) {
        pNewLine->Start.X = -pMapSpawn->pSpawn->X;
        pNewLine->Start.Y = -pMapSpawn->pSpawn->Y;
        pNewLine->Start.Z = pMapSpawn->pSpawn->Z;
        pNewLine->End.X = -pMapSpawn->pSpawn->X-pMapSpawn->pSpawn->SpeedX*4;
        pNewLine->End.Y = -pMapSpawn->pSpawn->Y-pMapSpawn->pSpawn->SpeedY*4;
        pNewLine->End.Z = pMapSpawn->pSpawn->Z+pMapSpawn->pSpawn->SpeedZ*4;
    } else {
        pNewLine->Start.X = -pMapSpawn->pSpawn->X;
        pNewLine->Start.Y = -pMapSpawn->pSpawn->Y;
        pNewLine->Start.Z = pMapSpawn->pSpawn->Z;
        pNewLine->End.X =-pMapSpawn->pSpawn->X-sinf(pMapSpawn->pSpawn->Heading/256.0f*(FLOAT)PI)*4;
        pNewLine->End.Y =-pMapSpawn->pSpawn->Y-cosf(pMapSpawn->pSpawn->Heading/256.0f*(FLOAT)PI)*4;
        pNewLine->End.Z =pMapSpawn->pSpawn->Z;
    }



    pNewLine->Layer = 3;
    pNewLine->Color = pMapSpawn->pMapLabel->Color;

    return pNewLine;    
}

DWORD MapHide(SEARCHSPAWN &Search)
{
    PCHARINFO pCharInfo=GetCharInfo();
    if (!pCharInfo)
        return 0;
    PMAPSPAWN pMapSpawn=pActiveSpawns;
    unsigned long Count=0;
    while(pMapSpawn)
    {
        if (pMapSpawn->pSpawn->Type!=FAKESPAWNTYPE && SpawnMatchesSearch(&Search,pCharInfo->pSpawn,pMapSpawn->pSpawn))
        {
            PMAPSPAWN pNext=pMapSpawn->pNext;
            RemoveSpawn(pMapSpawn);
            pMapSpawn=pNext;
            Count++;
        }
        else
            pMapSpawn=pMapSpawn->pNext;
    }
    return Count;
}

DWORD MapShow(SEARCHSPAWN &Search)
{
    PCHARINFO pCharInfo=GetCharInfo();
    if (!pCharInfo)
        return 0;

    PSPAWNINFO pSpawn=(PSPAWNINFO)pSpawnList;
    unsigned long Count=0;
    while(pSpawn)
    {
        if (!SpawnMap[pSpawn->SpawnID] && SpawnMatchesSearch(&Search,pCharInfo->pSpawn,pSpawn))
        {
            AddSpawn(pSpawn,true);
            Count++;
        }
        pSpawn=pSpawn->pNext;
    }
    return Count;
}

#ifndef ISXEQ
BOOL dataMapSpawn(PCHAR szIndex, MQ2TYPEVAR &Ret)
#else
bool dataMapSpawn(int argc, char *argv[], MQ2TYPEVAR &Ret)
#endif
{
    if (!pCurrentMapLabel)
        return false;
    if (PMAPSPAWN pMapSpawn=LabelMap[pCurrentMapLabel])
    {
        Ret.Ptr=pMapSpawn->pSpawn;
        Ret.Type=pSpawnType;
        return true;
    }
    return false;
}
void GenerateMarker(PMAPSPAWN pMapSpawn)
{
    if (pMapSpawn->Marker==0) return;
    long lNumSides = 4;

    if (pMapSpawn->Marker==1)
      lNumSides = 3;
    if (pMapSpawn->Marker==4)
	{
		lNumSides = 8;
	}
		

    long i;
    for (i = 0; i < 9; i++)
        pMapSpawn->MarkerLines[i] = NULL;

    for (i = 0; i < lNumSides; i++) {
        PMAPLINE pNewLine = InitLine();
        pNewLine->Start.X = 0;
        pNewLine->Start.Y = 0;
        pNewLine->Start.Z = pMapSpawn->pSpawn->Z;
        pNewLine->End.X = 0;
        pNewLine->End.Y = 0;
        pNewLine->End.Z = pMapSpawn->pSpawn->Z;
        pNewLine->Layer = 3;
        pNewLine->Color = pMapSpawn->pMapLabel->Color;
        pMapSpawn->MarkerLines[i] = pNewLine;
    }
}

void RemoveMarker(PMAPSPAWN pMapSpawn)
{
   if (pMapSpawn->Marker==0||!pMapSpawn->Marker) return;
   pMapSpawn->Marker=0;
   for (int i=0;pMapSpawn->MarkerLines[i];i++) {
      if (pMapSpawn->MarkerLines[i]) {
         DeleteLine(pMapSpawn->MarkerLines[i]);
         pMapSpawn->MarkerLines[i]=NULL;
      }
   }
}

void MSM(PMAPSPAWN pMapSpawn)
{
   DWORD MARKERSIDELEN = pMapSpawn->MarkerSize;
   float x[1],y[1],X[1],Y[1];
   if (pMapSpawn->Highlight)
   {
	   if (HighlightPulse)
	   {
		   MARKERSIDELEN = HighlightSIDELEN + (HighlightPulseIndex * HighlightPulseDiff);
	   }
	   else
	   {
		   MARKERSIDELEN = HighlightSIDELEN;
	   }
   }

    x[0] = -pMapSpawn->pSpawn->X - MARKERSIDELEN/2;
    x[1] = -pMapSpawn->pSpawn->X + MARKERSIDELEN/2;
    y[0] = -pMapSpawn->pSpawn->Y - MARKERSIDELEN/2;
    y[1] = -pMapSpawn->pSpawn->Y + MARKERSIDELEN/2;

    for (int i=0;i<4;i++) {
        switch (i) {
            case 0:   X[0]=x[0]; X[1]=x[1]; Y[0]=y[0]; Y[1]=y[0]; break;
         case 1:   X[0]=x[1]; X[1]=x[1]; Y[0]=y[0]; Y[1]=y[1]; break;
         case 2:   X[0]=x[1]; X[1]=x[0]; Y[0]=y[1]; Y[1]=y[1]; break;
         case 3:   X[0]=x[0]; X[1]=x[0]; Y[0]=y[1]; Y[1]=y[0]; break;
        }

        pMapSpawn->MarkerLines[i]->Start.X = X[0];
        pMapSpawn->MarkerLines[i]->Start.Y = Y[0];
        pMapSpawn->MarkerLines[i]->End.X = X[1];
        pMapSpawn->MarkerLines[i]->End.Y = Y[1];
        pMapSpawn->MarkerLines[i]->Start.Z = pMapSpawn->pSpawn->Z;
        pMapSpawn->MarkerLines[i]->End.Z = pMapSpawn->pSpawn->Z;

        if (pMapSpawn->MarkerLines[i]->Color.ARGB != pMapSpawn->pMapLabel->Color.ARGB)
           pMapSpawn->MarkerLines[i]->Color = pMapSpawn->pMapLabel->Color;
   }
}

void MTM(PMAPSPAWN pMapSpawn)
{
   DWORD MARKERSIDELEN = pMapSpawn->MarkerSize;
    float x[2],y[2],X[1],Y[1],Angle;
	if (pMapSpawn->Highlight)
	{
		if (HighlightPulse)
		{
			MARKERSIDELEN = HighlightSIDELEN + (HighlightPulseIndex * HighlightPulseDiff);
		}
		else
		{
			MARKERSIDELEN = HighlightSIDELEN;
		}
	}

    Angle = pMapSpawn->pSpawn->Heading*0.703125f;
    x[0] = -pMapSpawn->pSpawn->X+(MARKERSIDELEN*1.5f)*sqrtf(3)/3*sinf((Angle+180)/180.0f*(FLOAT)PI);
    x[1] = -pMapSpawn->pSpawn->X-(MARKERSIDELEN*1.5f)*sqrtf(3)/3*sinf((Angle+210)/180.0f*(FLOAT)PI);
    x[2] = -pMapSpawn->pSpawn->X+(MARKERSIDELEN*1.5f)*sqrtf(3)/3*sinf((Angle+330)/180.0f*(FLOAT)PI);
    y[0] = -pMapSpawn->pSpawn->Y+(MARKERSIDELEN*1.5f)*sqrtf(3)/3*cosf((Angle+180)/180.0f*(FLOAT)PI);
    y[1] = -pMapSpawn->pSpawn->Y-(MARKERSIDELEN*1.5f)*sqrtf(3)/3*cosf((Angle+210)/180.0f*(FLOAT)PI);
    y[2] = -pMapSpawn->pSpawn->Y+(MARKERSIDELEN*1.5f)*sqrtf(3)/3*cosf((Angle+330)/180.0f*(FLOAT)PI);

    for (int i=0;i<3;i++) {
        switch (i) {
         case 0:   X[0]=x[0]; X[1]=x[1]; Y[0]=y[0]; Y[1]=y[1]; break;
         case 1:   X[0]=x[1]; X[1]=x[2]; Y[0]=y[1]; Y[1]=y[2]; break;
         case 2:   X[0]=x[2]; X[1]=x[0]; Y[0]=y[2]; Y[1]=y[0]; break;
      }

       pMapSpawn->MarkerLines[i]->Start.X = X[0];
      pMapSpawn->MarkerLines[i]->Start.Y = Y[0];
      pMapSpawn->MarkerLines[i]->End.X = X[1];
      pMapSpawn->MarkerLines[i]->End.Y = Y[1];
      pMapSpawn->MarkerLines[i]->Start.Z = pMapSpawn->pSpawn->Z;
      pMapSpawn->MarkerLines[i]->End.Z = pMapSpawn->pSpawn->Z;

      if (pMapSpawn->MarkerLines[i]->Color.ARGB != pMapSpawn->pMapLabel->Color.ARGB)
         pMapSpawn->MarkerLines[i]->Color = pMapSpawn->pMapLabel->Color;
   }
}

void MDM(PMAPSPAWN pMapSpawn)
{
   DWORD MARKERSIDELEN = pMapSpawn->MarkerSize;
    float x[2],y[2],X[1],Y[1];
	if (pMapSpawn->Highlight)
	{
		if (HighlightPulse)
		{
			MARKERSIDELEN = HighlightSIDELEN + (HighlightPulseIndex * HighlightPulseDiff);
		}
		else
		{
			MARKERSIDELEN = HighlightSIDELEN;
		}
	}

    x[0] = -pMapSpawn->pSpawn->X;
    x[1] = -pMapSpawn->pSpawn->X + MARKERSIDELEN*.71f;   // sqrt(2)/2
    x[2] = -pMapSpawn->pSpawn->X - MARKERSIDELEN*.71f;
    y[0] = -pMapSpawn->pSpawn->Y - MARKERSIDELEN*.71f;
    y[1] = -pMapSpawn->pSpawn->Y;
    y[2] = -pMapSpawn->pSpawn->Y + MARKERSIDELEN*.71f;

    for (int i=0;i<4;i++) {
        switch (i) {
            case 0:   X[0]=x[0]; X[1]=x[1]; Y[0]=y[0]; Y[1]=y[1]; break;
         case 1:   X[0]=x[1]; X[1]=x[0]; Y[0]=y[1]; Y[1]=y[2]; break;
           case 2:   X[0]=x[0]; X[1]=x[2]; Y[0]=y[2]; Y[1]=y[1]; break;
          case 3:   X[0]=x[2]; X[1]=x[0]; Y[0]=y[1]; Y[1]=y[0]; break;
        }

      pMapSpawn->MarkerLines[i]->Start.X = X[0];
      pMapSpawn->MarkerLines[i]->Start.Y = Y[0];
      pMapSpawn->MarkerLines[i]->End.X = X[1];
      pMapSpawn->MarkerLines[i]->End.Y = Y[1];
      pMapSpawn->MarkerLines[i]->Start.Z = pMapSpawn->pSpawn->Z;
      pMapSpawn->MarkerLines[i]->End.Z = pMapSpawn->pSpawn->Z;

      if (pMapSpawn->MarkerLines[i]->Color.ARGB != pMapSpawn->pMapLabel->Color.ARGB)
         pMapSpawn->MarkerLines[i]->Color = pMapSpawn->pMapLabel->Color;
   }
}


void MRM(PMAPSPAWN pMapSpawn)
{
   DWORD MARKERSIDELEN = pMapSpawn->MarkerSize;
   if (pMapSpawn->Highlight)
   {
	   if (HighlightPulse)
	   {
		   MARKERSIDELEN = HighlightSIDELEN + (HighlightPulseIndex * HighlightPulseDiff);
	   }
	   else
	   {
		   MARKERSIDELEN = HighlightSIDELEN;
	   }
   }

    for (int i=0;i<8;i++) {

      pMapSpawn->MarkerLines[i]->Start.X = -pMapSpawn->pSpawn->X+MARKERSIDELEN*sinf((i*45+22.5)/180.0f*(FLOAT)PI);
      pMapSpawn->MarkerLines[i]->Start.Y = -pMapSpawn->pSpawn->Y+MARKERSIDELEN*cosf((i*45+22.5)/180.0f*(FLOAT)PI);
      pMapSpawn->MarkerLines[i]->End.X = -pMapSpawn->pSpawn->X+MARKERSIDELEN*sinf(((i+1)*45+22.5)/180.0f*(FLOAT)PI);
      pMapSpawn->MarkerLines[i]->End.Y = -pMapSpawn->pSpawn->Y+MARKERSIDELEN*cosf(((i+1)*45+22.5)/180.0f*(FLOAT)PI);
      pMapSpawn->MarkerLines[i]->Start.Z = pMapSpawn->pSpawn->Z;
      pMapSpawn->MarkerLines[i]->End.Z = pMapSpawn->pSpawn->Z;

      if (pMapSpawn->MarkerLines[i]->Color.ARGB != pMapSpawn->pMapLabel->Color.ARGB)
         pMapSpawn->MarkerLines[i]->Color = pMapSpawn->pMapLabel->Color;
   }
}

void MoveMarker(PMAPSPAWN pMapSpawn)
{
   switch (pMapSpawn->Marker) {
      case 1: //triangle
         MTM(pMapSpawn);
         return;
      case 2: //square
         MSM(pMapSpawn);
         return;
      case 3: //diamond
         MDM(pMapSpawn);
         return;
      case 4: //ring
         MRM(pMapSpawn);
         return;
   }
}





DWORD FindMarker(PCHAR szMark)
{
    if (!stricmp(szMark,"none"))
       return 0;
    else if (!stricmp(szMark,"triangle"))
       return 1;
    else if (!stricmp(szMark,"square"))
       return 2;
    else if (!stricmp(szMark,"diamond"))
       return 3;
    else if (!stricmp(szMark,"ring"))
       return 4;
    return 99;
}

// make a current timestamp in tenths of a second
long MakeTime()
{
   SYSTEMTIME st;
   ::GetSystemTime(&st);
   long lCurrent=0;
   lCurrent  = st.wDay    * 24 * 60 * 60 * 10;
   lCurrent += st.wHour        * 60 * 60 * 10;
   lCurrent += st.wMinute           * 60 * 10;
   lCurrent += st.wSecond                * 10;
   lCurrent += (long)(st.wMilliseconds/100);
   return (lCurrent);
}

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Re: Some Map enhancements for /highlight

Post by EqMule » Wed Jan 20, 2016 2:01 pm

Thanks for contributing, I added these now, should be in next release.
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

Botologist
a lesser mummy
a lesser mummy
Posts: 35
Joined: Fri Apr 27, 2007 9:07 am

Re: Some Map enhancements for /highlight

Post by Botologist » Wed Jan 20, 2016 9:51 pm

My map is not working with this update. Looks just like non-mq2 map. Any ideas?

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Re: Some Map enhancements for /highlight

Post by JudgeD » Wed Jan 20, 2016 10:03 pm

Botologist wrote:My map is not working with this update. Looks just like non-mq2 map. Any ideas?
:shock: Looking

SwiftyMUSE
Developer
Developer
Posts: 1205
Joined: Tue Sep 23, 2003 10:52 pm

Re: Some Map enhancements for /highlight

Post by SwiftyMUSE » Wed Jan 20, 2016 10:14 pm

Botologist wrote:My map is not working with this update. Looks just like non-mq2 map. Any ideas?
It does work. Do you have MQ2Map turned off, or do you have npcs, corpses, pcs, etc turned off and not on?
PayPal: Donate to SwiftyMUSE
Bitcoin: 1LuQ6YcEAWxF3fm9yWMiro4K582je7364V
Krono: PM me

dont_know_at_all wrote:Gee, if only there was a way to correctly report a crash...

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Re: Some Map enhancements for /highlight

Post by JudgeD » Wed Jan 20, 2016 10:16 pm

Confirmed that mine is working still. Double check that your ini file still exists in the root MQ folder and also that the commands work, such as "/mapfilter npc".

An example ini file that I use (may not be true vanilla version but should be ok):

Code: Select all

[Map Filters]
All=1
NPC=1
PC=1
NPCConColor=1
Target=1
TargetLine=1
TargetRadius=30
Vector=1
SpellRadius=200
Group=0
Menu=0
Custom=0
Marker=5
Mapshow=npc 
Maphide=npc
Trap=1
NormalLabels=1
TargetPath=1
Named=0
Corpse=1
Ground=1
Object=1
CastRadius=0
Trigger=1
NPCCorpse=1
PCCorpse=1
Chest=1
Mercenary=0
Mercenary-Color=4210752
Pet=0
Aura=0
HighSize=100
HighPulse=1
[Naming Schemes]
Normal=%N
Target=%N
[Marker Filters]
PC=Square
PC-Size=25
NPC=Diamond
NPC-Size=10
Named=Square
Named-Size=50

Botologist
a lesser mummy
a lesser mummy
Posts: 35
Joined: Fri Apr 27, 2007 9:07 am

Re: Some Map enhancements for /highlight

Post by Botologist » Wed Jan 20, 2016 10:23 pm

did not know you could turn it off but I copied my mq2map.ini file from previous build and pasted it into this one and no go.

I usually run with pc on, group on, npc on, npcconcolor on, ground on, corpse on, target on, normallabels on.

/mapfilter shows these as being on

/plugin list shows mq2map loaded.

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Re: Some Map enhancements for /highlight

Post by JudgeD » Wed Jan 20, 2016 10:38 pm

double check that all map layers are enabled?

Botologist
a lesser mummy
a lesser mummy
Posts: 35
Joined: Fri Apr 27, 2007 9:07 am

Re: Some Map enhancements for /highlight

Post by Botologist » Wed Jan 20, 2016 10:40 pm

Ah...that was it.
many thanks JudgeD

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Re: Some Map enhancements for /highlight

Post by JudgeD » Wed Jan 20, 2016 10:44 pm

whew :smile:

SwiftyMUSE
Developer
Developer
Posts: 1205
Joined: Tue Sep 23, 2003 10:52 pm

Re: Some Map enhancements for /highlight

Post by SwiftyMUSE » Thu Jan 21, 2016 9:38 am

JudgeD wrote:double check that all map layers are enabled?
MQ2Map uses layer 2
PayPal: Donate to SwiftyMUSE
Bitcoin: 1LuQ6YcEAWxF3fm9yWMiro4K582je7364V
Krono: PM me

dont_know_at_all wrote:Gee, if only there was a way to correctly report a crash...

iluvseq
Clueless Mudslinger
Posts: 269
Joined: Mon Apr 14, 2003 10:05 am

Re: Some Map enhancements for /highlight

Post by iluvseq » Thu Jan 21, 2016 12:05 pm

The new command breaks ISXEQ compilation. Simple fix, just need to move the #endif at line 538 back down to the end of the file to effectively comment all of this out for ISXEQ users.

JudgeD
a snow griffon
a snow griffon
Posts: 354
Joined: Sat Aug 18, 2012 8:07 pm

Re: Some Map enhancements for /highlight

Post by JudgeD » Thu Apr 07, 2016 9:37 pm

Because I screwed up last time I posted those map updates (moved things to layer 3 by accident), I decided to add a command to allow folks to set which layer map is active on. The setting persists to file if changed, otherwise defaults to layer 2 like it always has. Kinda nice :)

MQ2MapCommands.cpp:

Code: Select all

VOID MapActiveLayerCmd(PSPAWNINFO pChar, PCHAR szLine)
{
	CHAR szBuffer[MAX_STRING] = { 0 };
	bRunNextCommand = TRUE;
	int newActiveLayer = atoi(szLine);
	if (szLine == 0 || szLine[0] == 0 || newActiveLayer < 0 || newActiveLayer > 3)
	{
		SyntaxError("Usage: /mapactivelayer [0|1|2|3]");
		return;
	};

	activeLayer = newActiveLayer;
	
	sprintf(szBuffer, "Map Active Layer: %d", activeLayer);
	WriteChatColor(szBuffer);

	// Write setting to file
	char szTest[5];
	sprintf_s(szTest, "%d", activeLayer);
	WritePrivateProfileString("Map Filters", "ActiveLayer", szTest, INIFileName);

	// refresh map
	MapClear();
	MapGenerate();
}
MQ2MapAPI.cpp:
(change every reference of "...Layer = 2" to "...Layer = activeLayer") Should be 8 total.

MQ2Map.cpp:
Top of file set field:

Code: Select all

int activeLayer = 2;
Inside: PLUGIN_API VOID InitializePlugin(VOID)

Code: Select all

activeLayer = GetPrivateProfileInt("Map Filters", "ActiveLayer", activeLayer, INIFileName);
and

Code: Select all

AddCommand("/mapactivelayer", MapActiveLayerCmd, 0, 1, 1);
Inside: PLUGIN_API VOID ShutdownPlugin(VOID)

Code: Select all

RemoveCommand("/mapactivelayer");
MQ2Map.h:

Code: Select all

extern int activeLayer;

Code: Select all

VOID MapActiveLayerCmd(PSPAWNINFO pChar, PCHAR szLine);