-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMQ2MoveUtils.cpp
More file actions
8163 lines (7667 loc) · 318 KB
/
MQ2MoveUtils.cpp
File metadata and controls
8163 lines (7667 loc) · 318 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***** NOTICE ******
Many functions included in this source code are not copyrighted to the developer and are used with permissions
restricting their release to VIP board members of MacroQuest2.com. These functions have comments above them stating
to whom the copyright belongs to. If you intend to redistribute this source or binaries compiled from this source
outside of a direct link to the forum post in which it is released, you must get permission from these authors. Otherwise
link to the forum post directly to encourage any users of this plugin to donate to the developers at MacroQuest2.com
as required by the copyright holders of these functions, and desired by the developer. Please show your support!
****************/
// version information
//Version 12.0 Added string safety. Fixed Blech crash. - EqMule Jul 19 2016
//Version 12.1 Added new savecode and fixed the offsetfinder - EqMule Sep 12 2017
//Version 12.2 Updated patterns - SwiftyMUSE Feb 21 2018
//Version 12.3 Moved patterns - SwiftyMUSE Apr 23 2018
//Version 12.4 Fixed a NULL ptr crash - EqMule May 28 2018
#include <mq/Plugin.h>
#include <cmath>
constexpr auto PLUGIN_NAME = "MQ2MoveUtils";
PLUGIN_VERSION(12.5);
PreSetup(PLUGIN_NAME);
// uncomment these lines to enable debugspew spam
//#define DEBUGMAIN
// debugspew for stucklogic
//#define DEBUGSTUCK
// debugspew for trivial messages
//#define DEBUGMISC
Blech *pMoveEvent = 0;
// ------------------------------------------------------------------------------
// constants - the unsigned chars are aesthetics but we use different values
// so that nothing can be called incorrectly and erroneously match a switch case
// ------------------------------------------------------------------------------
// check calling command
const unsigned char CMD_STICK = 1;
const unsigned char CMD_MOVETO = 2;
const unsigned char CMD_CIRCLE = 3;
const unsigned char CMD_MAKECAMP = 4;
// walk handling
const unsigned char MU_WALKON = 10;
const unsigned char MU_WALKOFF = 11;
const unsigned char MU_WALKIGNORE = 12;
// reset altcamp or make new altcamp
const unsigned char SET_ALT = 20;
const unsigned char RESET_ALT = 21;
// direction to move
const unsigned char GO_FORWARD = 30;
const unsigned char GO_BACKWARD = 31;
const unsigned char GO_LEFT = 32;
const unsigned char GO_RIGHT = 33;
const unsigned char KILL_STRAFE = 34;
const unsigned char KILL_FB = 35;
const unsigned char APPLY_TO_ALL = 36;
// help output
const unsigned char HELP_SETTINGS = 50;
// error messages
const unsigned char ERR_STICKSELF = 60;
const unsigned char ERR_STICKNONE = 61;
const unsigned char ERR_BADMOVETO = 62;
const unsigned char ERR_BADMAKECAMP = 63;
const unsigned char ERR_BADCIRCLE = 64;
const unsigned char ERR_BADSPAWN = 65;
const unsigned char ERR_BADDELAY = 66;
// debug output
const unsigned char DBG_MAIN = 200;
const unsigned char DBG_STUCK = 201;
const unsigned char DBG_MISC = 202;
const unsigned char DBG_DISABLE = 203;
// ------------------------------------------
// formulas & randomization
const float CIRCLE_QUARTER = 90.0f;
const float CIRCLE_HALF = 180.0f;
const float CIRCLE_MAX = 360.0f;
const float HEADING_QUARTER = 128.0f;
const float HEADING_HALF = 256.0f;
const float HEADING_MAX = 512.0f;
const int BEHIND_ARC = 45;
const int FRONT_ARC = 240;
const int NOT_FRONT_ARC = 135;
const int PIN_ARC_MIN = 112;
const int PIN_ARC_MAX = 144;
// initialization
const float H_INACTIVE = 10000.0f;
const char H_FAST = 0;
const char H_LOOSE = 1;
const char H_TRUE = 2;
const char T_INACTIVE = 0;
const char T_WAITING = 1;
const char T_READY = 2;
// stucklogic ring size
const int MAXRINGSIZE = 32; // MovingAvg max pulses to average
// ------------------------------------------
// class instances
class CMUSettings* SET = NULL;
class CMUActive* pMU = NULL;
class CMUCharacter* ME = NULL;
class CMUWndHandler* WINDOW = NULL;
class CMUMovement* MOVE = NULL;
class CStickCmd* STICK = NULL;
class CMoveToCmd* MOVETO = NULL;
class CCircleCmd* CIRCLE = NULL;
class CStuckLogic* STUCK = NULL;
class CCampHandler* CAMP = NULL;
class CAltCamp* ALTCAMP = NULL;
class CCampCmd* CURCAMP = NULL;
class CPauseHandler* PAUSE = NULL;
class CMULoc* SUMMON = NULL;
class CCircleSettings* SET_C = NULL;
class CMoveToSettings* SET_M = NULL;
class CCampSettings* SET_CAMP = NULL;
class CStickSettings* SET_S = NULL;
// ---------------------------------
// verbosity bit flags
enum VERBLEVEL {
V_SILENCE = 0,
V_AUTOPAUSE = 1,
V_MOVEPAUSE = 2,
V_MOUSEPAUSE = 4,
V_FEIGN = 8,
V_HIDEHELP = 16,
V_STICKV = 32,
V_STICKFV = 64,
V_MOVETOV = 128,
V_MOVETOFV = 256,
V_MAKECAMPV = 512,
V_MAKECAMPFV = 1024,
V_CIRCLEV = 2048,
V_CIRCLEFV = 4096,
V_SETTINGS = 8192,
V_SAVED = 16384,
V_BREAKONWARP = 32768,
V_BREAKONAGGRO = 65536,
V_BREAKONHIT = 131072,
V_BREAKONSUMMON = 262144,
V_BREAKONGM = 524288,
V_BREAKONGATE = 1048576,
V_STICKALWAYS = 2097152,
V_ERRORS = 4194304,
V_RANDOMIZE = 8388608,
V_PAUSED = 16777216,
V_VERBOSITY = 2720, // normal verbosity msgs
V_FULLVERBOSITY = 11736390, // full verbosity msgs
V_EVERYTHING = 33554431, // all messages on (dont add verb + fullverb in)
};
unsigned int uiVerbLevel = V_EVERYTHING;
unsigned int uiRetainFlags = V_EVERYTHING; // stores flags for when totalsilence toggle
// -----------------------
// import / export
PLUGIN_API float fStickDistance = 0; // exporting to share the distance we're sticking.
PLUGIN_API bool bStickOn = false; // stick active or off, exported for other plugins to have a sure way of always knowing
PLUGIN_API void StickCommand(PlayerClient* pLPlayer, char* szLine); // exported wrapper for MQ2Melee support
// note to any developers: if you intend to use these exports and want to shut off stick, do not flip STICK->On directly,
// instead, call StickCommand(pLPlayer, "off")
bool* pbMULoaded = NULL; // imported from mq2melee in InitializePlugin()
bool bWrapped = false; // hi htw!
// -----------------------
// strings
char szMsg[MAX_STRING] = {}; // use for generic msg output
char szDebugName[MAX_STRING] = {}; // debug file name
char szCharName[MAX_STRING] = {}; // stores char name for INI read/write
const char szOn[10] = "\agON\ax"; // used in outputs
const char szOff[10] = "\arOFF\ax"; // used in outputs
const char szArriveMove[50] = "/moveto location"; // output moveto arrival
const char szArriveCamp[50] = "camp from /makecamp return"; // output camp return arrival
const char szArriveAlt[50] = "camp from /makecamp altreturn"; // output altcamp return arrival
// ----------------------------------------
// events
unsigned int Event_AggroNorm = NULL;
unsigned int Event_MissNorm = NULL;
unsigned int Event_AggroAbbrev = NULL;
unsigned int Event_MissAbbrev = NULL;
unsigned int Event_MissNumOnly = NULL;
unsigned int Event_Gates = NULL;
// ----------------------------------------
// function prototypes
void SpewMUError(unsigned char ucErrorNum);
void SpewDebug(unsigned char ucDbgType, const char* szOuput, ...);
void OutputHelp(unsigned char ucCmdUsed, bool bOnlyCmdHelp = false);
void WriteLine(const char* szOutput, VERBLEVEL V_COMPARE);
void HandleOurCmd(unsigned char ucCmdUsed, const char* szInput);
void EndPreviousCmd(bool bKillMovement, unsigned char ucCmdUsed = APPLY_TO_ALL, bool bPreserveSelf = false);
void ChangeSetting(unsigned char ucCmdUsed, bool bToggle, char szSetting[MAX_STRING]);
void SaveConfig();
void LoadConfig();
void DebugToWnd(unsigned char ucCmdUsed);
void DebugToINI(unsigned char ucCmdUsed);
void DebugToDebugger(const char* szFormat, ...);
void SetupEvents(bool bAddEvent, bool bForceRemove = false);
inline bool ValidIngame(bool bCheckDead = true);
// ----------------------------------------
// ************* CLASSES *****************
// ----------------------------------------
// ----------------------
// inherit-only classes
class CMULoc
{
// locations & dist comparisons
public:
float Y;
float X;
float Z;
float CurDist;
float DifDist;
CMULoc()
{
Y = 0.0f;
X = 0.0f;
Z = 0.0f;
CurDist = 0.0f;
DifDist = 0.0f;
}
};
class CMUDelay
{
// delay & time calculations
public:
int Min;
int Max;
void TimeStop()
{
Resume = T_INACTIVE;
}
void TimeStart()
{
GetSystemTime(&Began);
Resume = rand() % (Max - Min + 1) + Min;
}
char TimeStatus()
{
if (Resume == T_INACTIVE)
{
return T_INACTIVE;
}
if (ElapsedMS() >= Resume)
{
return T_READY;
}
return T_WAITING;
}
void Validate()
{
MinDelay(Min);
MaxDelay(Max);
}
void MinDelay(int iNew)
{
Min = iNew;
if (Min < 125) Min = 125;
}
void MaxDelay(int iNew)
{
Max = iNew;
if (Max < Min + 125) Max = Min + 125;
}
CMUDelay()
{
Min = 0;
Max = 0;
Resume = T_INACTIVE;
}
protected:
int Resume; // calculated resume time
SYSTEMTIME Began; // timer start
int ElapsedMS()
{
SYSTEMTIME stCurr, stResult;
FILETIME ftPrev, ftCurr, ftResult;
ULARGE_INTEGER prev, curr, result;
GetSystemTime(&stCurr);
SystemTimeToFileTime(&Began, &ftPrev);
SystemTimeToFileTime(&stCurr, &ftCurr);
prev.HighPart = ftPrev.dwHighDateTime;
prev.LowPart = ftPrev.dwLowDateTime;
curr.HighPart = ftCurr.dwHighDateTime;
curr.LowPart = ftCurr.dwLowDateTime;
result.QuadPart = curr.QuadPart - prev.QuadPart;
ftResult.dwHighDateTime = result.HighPart;
ftResult.dwLowDateTime = result.LowPart;
FileTimeToSystemTime(&ftResult, &stResult);
return ((int)(stResult.wSecond * 1000 + stResult.wMilliseconds));
}
};
// ----------------------------------------
// character functions
class CMUCharacter
{
public:
bool IsBard()
{
return pLocalPC && pLocalPlayer && pLocalPlayer->mActorClient.Class == Bard;
}
bool InCombat()
{
if (ValidIngame() && pPlayerWnd->CombatState == 0 && pPlayerWnd->GetChildItem("PW_CombatStateAnim"))
{
return true;
}
return false;
}
bool IsMe(PlayerClient* pCheck)
{
if (!pCheck || !pLocalPlayer) return false;
if (pCheck->SpawnID == pCharSpawn->SpawnID || pCheck->SpawnID == pLocalPlayer->SpawnID)
{
return true;
}
return false;
}
};
// ----------------------------------------------------------
// configuration classes - store default & INI-saved settings
class CStuckLogic : public CMULoc
{
public:
bool On; // INI: stucklogic active or off
bool Jump; // INI: if true, try to jump when stuck
bool TurnHalf; // INI: if true, reset heading and try other dir if gone halfway without freeing
unsigned int Check; // INI: # of pulses to average distance for stuck awareness
unsigned int Unstuck; // INI: if StuckDec == this, consider unstuck
float Dist; // INI: dist needed to move else considered stuck, compared against pulse average
float TurnSize; // Turn increment value for left/right (sign flipped by TurnHalf)
unsigned int StuckInc; // increments each pulse we haven't moved beyond Dist until we reach Check value which == we are stuck
unsigned int StuckDec; // increments each pulse we've moved again after being stuck, when Unstuck = StuckDec, we force unstuck
void Reset()
{
Y = X = Z = 0.0f;
DifDist = 0.0f;
CurDist = 1.0f;
StuckInc = 0;
StuckDec = 0;
}
CStuckLogic()
{
// plugin defaults established here
On = true;
Jump = false;
TurnHalf = true;
TurnSize = 10.0f;
Dist = 0.1f;
Check = 6;
Unstuck = 10;
StuckInc = 0;
StuckDec = 0;
CurDist = 1.0f; // baseline to not trigger when first starting movement
// Y X Z DifDist already initialized by CMULoc() inherit
}
};
class CStickSettings : public CMUDelay
{
public:
bool BreakGate; // INI: stick breaks if "mob_name Gates." message
bool BreakHit; // INI: stick breaks if npc is attacking
bool BreakTarget; // INI: stick breaks if target switched
bool BreakWarp; // INI: stick breaks if target warps out of DistBreak
bool Flex; // INI: stick flexibility when close
bool PauseWarp; // INI: stick pauses if target warps out of DistBreak
bool Randomize; // INI: randomize strafe arcs during stick
bool DelayStrafe; // INI: strafe sticks use a delay timer with TimedStrafe()
bool UseBack; // INI: use backwards walking when close to target
bool UseFleeing; // INI: 'front' will not strafe if target is fleeing
bool Walk; // INI: stick walks when strafing
bool UW; // look angle up or down at target (/stick uw)
float ArcBehind; // INI: arc size for stick behind
float ArcNotFront; // INI: arc size for stick !front
float DistBack; // INI: within this dist UseBack handles positioning if enabled
float DistBreak; // INI: target warps this distance, BreakWarp triggers if enabled
float DistFlex; // INI: distance for flexibility
float DistMod; // INI: raw modifier to Dist (CStickCmd) (best used if plugin is auto-setting dist)
float DistModP; // INI: % modifier to Dist (CStickCmd) (best used if plugin is auto-setting dist)
float DistSnap; // INI: default distance from target to snaproll
CStickSettings()
{
// plugin defaults, established here
Min = 1500; // inherit: CMUDelay (for strafe)
Max = 3000; // inherit: CMUDelay (for strafe)
BreakGate = true;
BreakHit = false;
BreakTarget = false;
BreakWarp = true;
PauseWarp = false;
Flex = false;
Randomize = false;
DelayStrafe = true;
UseBack = true;
UseFleeing = true;
Walk = false;
UW = false;
ArcBehind = BEHIND_ARC;
ArcNotFront = NOT_FRONT_ARC;
DistBack = 10.0f;
DistBreak = 250.0f;
DistFlex = 7.0f;
DistMod = 0.0f;
DistModP = 1.0f;
DistSnap = 10.0f;
}
};
class CCampSettings : public CMUDelay
{
public:
bool HaveTarget; // INI: if true, auto camp return even with a target
bool NoAggro; // INI: if true, auto camp return only if not aggro
bool NotLoot; // INI: if true, auto camp return only if not looting
bool Scatter; // INI: camp return scattering active or off
bool Realtime; // INI: makecamp player updates pc anchor Y/X while returning
bool Leash; // INI: camp leashing active or off
float Bearing; // INI: bearing for camp return scattering
float Length; // INI: length of leash checked against anchor
float Radius; // INI: default camp radius size
float ScatSize; // INI: camp return scatter radius size
float ScatDist; // INI: dist from anchor for camp return scattering
CCampSettings()
{
Min = 500; // inherit: CMUDelay
Max = 1500; // inherit: CMUDelay
HaveTarget = false;
NoAggro = false;
NotLoot = false;
Scatter = false;
Realtime = false;
Leash = false;
Bearing = 0.0f;
Length = 50.0f;
Radius = 40.0f;
ScatSize = 10.0f;
ScatDist = 10.0f;
}
void SetRadius(float fNew)
{
Radius = fNew;
ValidateSizes();
}
void SetLeash(float fNew)
{
Length = fNew;
ValidateSizes();
}
protected:
void ValidateSizes()
{
if (Radius < 5.0f) Radius = 5.0f; // enforce min Radius size 5.0f
float fTemp = Radius + 5.0f;
if (Length < fTemp) Length = fTemp; // enforce min leash size 5.0f >= Radius
}
};
class CMoveToSettings
{
public:
bool BreakAggro; // INI: break moveto if aggro gained
bool BreakHit; // INI: break moveto if attacked (blech event)
bool UseBack; // INI: use backwards walking when initially close to destination
bool UW; // INI: moveto uses UW face angle adjustments
bool Walk; // INI: moveto walks if close to arrivaldist
float Dist; // INI: how close to moveto location is considered acceptable
float DistBack; // INI: within this dist UseBack handles positioning if enabled
float DistY; // INI: how close to moveto Y location is acceptable for precisey
float DistX; // INI: how close to moveto X location is acceptable for precisex
float Mod; // INI: Dist percent modifier
CMoveToSettings()
{
BreakAggro = false;
BreakHit = false;
UseBack = false;
UW = false;
Walk = true;
Dist = 10.0f;
DistBack = 30.0f;
DistY = 10.0f;
DistX = 10.0f;
Mod = 0.0f;
}
};
class CCircleSettings
{
public:
bool Backward; // INI: always backwards
bool CCW; // INI: always counter-clockwise
bool Drunk; // INI: always drunken
float CMod; // INI: default radius percent modifer
float Radius; // INI: default radius size
CCircleSettings()
{
Backward = false;
CCW = false;
Drunk = false;
CMod = 0.0f;
Radius = 30.0f;
}
void SetRadius(float fNew)
{
// enforce min radius size 5.0f
Radius = fNew;
if (Radius < 5.0f) Radius = 5.0f;
}
};
class CMUSettings
{
public:
bool AutoSave; // INI: autosave ini file when using 'toggle' or 'set'
bool AutoPause; // INI: pause automatically when casting/stunned/self targeted/sitting
bool AutoUW; // INI: automatically use 'uw' when underwater
bool BreakGM; // INI: command breaks if visible GM enters zone
bool BreakSummon; // INI: command breaks if you move too far in a single pulse (summoned)
bool BreakKB; // INI: break command if movement key pressed
bool PauseKB; // INI: pause command if movement key pressed
bool BreakMouse; // INI: break command if mouselook active
bool PauseMouse; // INI: pause command if mouselook active
bool Feign; // INI: do not stand if currently FD
bool LockPause; // INI: pause will not reset until unpaused
bool SaveByChar; // INI: save some settings for individual characters
bool Spin; // INI: if true, stick front ignores requiring being on HoTT
bool Window; // INI: use dedicated UI window
bool WinEQ; // INI: use old-style movement
float AllowMove; // INI: distance to allow forward movement while turning, CanLooseMove()
float DistSummon; // INI: distance your character moves in a single pulse to trigger BreakSummon
float TurnRate; // INI: rate at which to turn using loose heading (14 is default)
int Head; // INI: heading adjustment type (0 = fast [H_FAST], 1 = loose [H_LOOSE], 2 = true [H_TRUE])
CMUSettings()
{
SET_CAMP = new CCampSettings();
SET_S = new CStickSettings();
SET_M = new CMoveToSettings();
SET_C = new CCircleSettings();
AutoSave = true;
AutoPause = true;
AutoUW = false;
BreakGM = true;
BreakSummon = false;
BreakKB = true;
PauseKB = false;
BreakMouse = false;
PauseMouse = false;
Feign = false;
LockPause = false;
SaveByChar = true;
Spin = false;
Window = false;
WinEQ = false;
AllowMove = 32.0f;
DistSummon = 8.0f;
TurnRate = 14.0f;
Head = H_TRUE;
}
~CMUSettings()
{
delete SET_CAMP;
SET_CAMP = NULL;
delete SET_S;
SET_S = NULL;
delete SET_M;
SET_M = NULL;
delete SET_C;
SET_C = NULL;
}
};
// ---------------------------------------------------
// command classes - instanced for individual cmd use
class CCircleCmd : public CMULoc, public CMUDelay, public CCircleSettings
{
public:
bool On; // circling active or off
bool Wait()
{
// drunken circling uses this formula
if (ElapsedMS() > Max + GetDrunk(Min))
{
TimeStart();
return false;
}
return true;
}
void AtMe()
{
// HandleOurCmd calls this to establish '/circle on' without loc supplied
PlayerClient* pChSpawn = pCharSpawn;
Y = pChSpawn->Y + Radius * sin(pChSpawn->Heading * (float)PI / HEADING_HALF);
X = pChSpawn->X + Radius * cos(pChSpawn->Heading * (float)PI / HEADING_HALF);
On = true;
}
void AtLoc(float fY, float fX)
{
// HandleOurCmd calls this with desired Y X supplied
Y = fY;
X = fX;
On = true;
}
CCircleCmd() // ooo: CMULoc(), CMUDelay(), CCircleSettings(), CCircleCmd()
{
Min = 600; // inherit: CMUDelay
Max = 900; // inherit: CMUDelay
On = false;
UserDefaults(); // copy defaults from INI settings
TimeStart();
}
protected:
void UserDefaults()
{
Backward = SET_C->Backward;
CCW = SET_C->CCW;
Drunk = SET_C->Drunk;
CMod = SET_C->CMod;
Radius = SET_C->Radius;
}
int GetDrunk(int iNum)
{
return (iNum * rand() / (RAND_MAX + 1));
}
};
class CMoveToCmd : public CMULoc, public CMoveToSettings
{
public:
bool On; // moveto active or off (MOVETO->On)
bool PreciseY; // moveto arrivaldist is only checked against Y
bool PreciseX; // moveto arrivaldist is only checked against X
bool DidAggro();
CMoveToCmd()
{
On = false;
PreciseY = false;
PreciseX = false;
UserDefaults();
}
void Activate(float fY, float fX, float fZ)
{
Y = fY;
X = fX;
Z = fZ;
On = true;
}
protected:
void UserDefaults()
{
BreakAggro = SET_M->BreakAggro;
BreakHit = SET_M->BreakHit;
UseBack = SET_M->UseBack;
UW = SET_M->UW;
Walk = SET_M->Walk;
Dist = SET_M->Dist;
DistBack = SET_M->DistBack;
DistY = SET_M->DistY;
DistX = SET_M->DistX;
Mod = SET_M->Mod;
}
};
class CCampCmd : public CMULoc, public CCampSettings
{
public:
bool On; // camp active or off
bool Pc; // makecamp player on or off
bool RedoStick; // set during camp return
bool RedoCircle; // set during camp return
unsigned long PcID; // stores id of makecamp player
eSpawnType PcType; // stores spawn type of makecamp player
char PcName[MAX_STRING]; // stores makecamp player displayedname
CCampCmd()
{
On = false;
Pc = false;
RedoStick = false;
RedoCircle = false;
PcID = 0;
PcType = NONE;
memset(&PcName, 0, MAX_STRING);
UserDefaults();
}
protected:
void UserDefaults()
{
Min = SET_CAMP->Min;
Max = SET_CAMP->Max;
HaveTarget = SET_CAMP->HaveTarget;
NoAggro = SET_CAMP->NoAggro;
NotLoot = SET_CAMP->NotLoot;
Scatter = SET_CAMP->Scatter;
Realtime = SET_CAMP->Realtime;
Leash = SET_CAMP->Leash;
Bearing = SET_CAMP->Bearing;
Length = SET_CAMP->Length;
Radius = SET_CAMP->Radius;
ScatSize = SET_CAMP->ScatSize;
ScatDist = SET_CAMP->ScatDist;
}
};
class CAltCamp : public CMULoc
{
public:
bool On;
float Radius;
void Update(CCampCmd* Cur)
{
Y = Cur->Y;
X = Cur->X;
Radius = Cur->Radius;
On = true;
}
CAltCamp()
{
On = false;
Radius = 0.0f;
}
};
class CCampHandler : public CMUDelay, public CMULoc
{
public:
bool Auto; // state awareness (is camp return auto or manual)
bool DoAlt; // true when manually forcing a return to altcamp
bool DoReturn; // true when manually forcing a return to curcamp
bool Returning; // true when any return is active (both auto and manual)
void ResetBoth()
{
delete ALTCAMP;
ALTCAMP = new CAltCamp();
delete CURCAMP;
CURCAMP = new CCampCmd();
}
void ResetCamp(bool bOutput)
{
ALTCAMP->Update(CURCAMP);
NewCamp(bOutput);
}
void ResetPlayer(bool bOutput)
{
NewCamp(false);
if (bOutput) OutputPC();
}
void NewCamp(bool bOutput)
{
if (ValidIngame() && MOVETO->On && Returning)
{
// kill active camp return
EndPreviousCmd(true);
}
delete CURCAMP;
CURCAMP = new CCampCmd();
VarReset();
if (bOutput) Output();
}
void Activate(float fY, float fX)
{
if (CURCAMP->On && !CURCAMP->Pc)
{
ResetCamp(false);
}
else
{
NewCamp(false);
}
CURCAMP->On = true;
CURCAMP->Y = fY;
CURCAMP->X = fX;
Validate(); // CMUDelay
}
void ActivatePC(PlayerClient* pCPlayer)
{
Activate(pCPlayer->Y, pCPlayer->X);
sprintf_s(CURCAMP->PcName, "%s", pCPlayer->DisplayedName);
CURCAMP->Pc = true;
CURCAMP->PcID = pCPlayer->SpawnID;
CURCAMP->PcType = GetSpawnType(pCPlayer);
}
void VarReset()
{
Auto = false;
DoAlt = false;
DoReturn = false;
Returning = false;
}
CCampHandler()
{
ALTCAMP = new CAltCamp();
CURCAMP = new CCampCmd();
Min = SET_CAMP->Min;
Max = SET_CAMP->Max;
VarReset();
}
~CCampHandler()
{
delete ALTCAMP;
ALTCAMP = NULL;
delete CURCAMP;
CURCAMP = NULL;
}
protected:
void Output()
{
sprintf_s(szMsg, "\ay%s\aw:: MakeCamp off.", PLUGIN_NAME);
WriteLine(szMsg, V_MAKECAMPV);
}
void OutputPC()
{
sprintf_s(szMsg, "\ay%s\aw:: MakeCamp player off.", PLUGIN_NAME);
WriteLine(szMsg, V_MAKECAMPV);
}
};
class CSnaproll : public CMULoc
{
public:
float Head; // heading to snaproll
float Bearing; // bearing of target to snaproll to
CSnaproll()
{
Head = 0.0f;
Bearing = HEADING_HALF;
}
};
class CStickCmd : public CMULoc, public CStickSettings
{
public:
CSnaproll* Snap; // instance a snaproll
// active stick settings
bool SetDist; // has dist to mob has been set
float Dist; // defaults to melee range or set to 10 by /stick 10 for example
float RandMin; // min arc for strafe (if randomize enabled)
float RandMax; // max arc for strafe (if randomize enabled)
bool RandFlag; // flag to randomly randomize min or max
// active stick type
bool MoveBack; // maintains distance (if too close, back up)
bool Behind; // uses rear arc of target
bool BehindOnce; // moves to rear arc of target then position is ignored
bool Front; // uses front arc of target
bool NotFront; // uses anywhere but the front arc of target (/stick !front)
bool Pin; // uses left or right arc of the target
bool Snaproll; // snaprolls to a fixed loc (polarmath) instead of strafing
bool Hold; // maintains sticking to previous target if it changes
bool Healer; // healer type (non-constant facing)
bool Always; // restick when new target acquired (wont work with hold) (/stick __ always)
bool HaveTarget; // true when Always true and have a target
bool Strafe; // true when using a cmd that will strafe other than 'front'
bool On; // stick active or off, set this only through TurnOn()
// spawn information
unsigned long theLastID = 0; // compare target change OnPulse
unsigned long HoldID = 0; // spawn id for stick hold
eSpawnType LastType; // if target changes to a corpse, stop sticking
eSpawnType HoldType; // if stick hold changes to a corpse, stop sticking
void TurnOn()
{
On = true;
bStickOn = true; // mq2melee support until setup valid/updated pointer to the class member
}
void StopHold()
{
HoldID = NULL;
HoldType = NONE;
Hold = false;
}
void FirstAlways()
{
// reset hold values, dont allow 'hold' or 'id' with 'always'
StopHold();
Always = true;
TurnOn();
if (pTarget)
{
HaveTarget = true;
return;
}
HaveTarget = false;
}
void NewSnaproll()
{
delete Snap;
Snap = new CSnaproll();
}
void ResetLoc()
{
Y = X = Z = 0.0f;
CurDist = DifDist = 0.0f;
}
bool Ready()
{
if (Always)
{
return AlwaysStatus();
}
return On;
}
void DoRandomize()
{
if (!Randomize) return;
if (NotFront)
{
SetRandArc(NOT_FRONT_ARC);
}
else if (Behind)
{
SetRandArc(BEHIND_ARC);
}
else if (Pin)
{
SetRandArc(PIN_ARC_MIN);
}
}
CStickCmd()
{
Snap = new CSnaproll();
SetDist = false;
Dist = 0.0f;
RandMin = 0.0f;
RandMax = 0.0f;
RandFlag = true;
MoveBack = false;
Behind = false;
BehindOnce = false;
Front = false;
NotFront = false;
Pin = false;