Scripts/Instances: Complete rewrite of the boundary system.

- Migrate boundary logic to Maps/AreaBoundary instead of having it sit in InstanceScript (to possibly allow use for other purposes).
- Implement the first five boundary types in Maps/AreaBoundary.cpp.
- Add boundary checks to Creature's update logic
- Add boundary data for all Northrend raids
- Add boundary initialization structures and methods to InstanceScript
- Modify EnterEvadeMode signature. It now passes a value from the EvadeReason enum as parameter to allow special casing depending on evade reason
- Remove previous (weird) boundary code that had them linked to GO spawns
This commit is contained in:
treeston committed 2016-01-12 22:24:23 +01:00
1 parent 60e3127714
commit 2da458c56d
134 files changed
+985 -533

No files matched your search

+3 -3
View File
@@ -375,7 +375,7 @@ CREATE TABLE `rbac_linked_permissions` (
LOCK TABLES `rbac_linked_permissions` WRITE;
/*!40000 ALTER TABLE `rbac_linked_permissions` DISABLE KEYS */;
INSERT INTO `rbac_linked_permissions` VALUES (192,21),(192,42),(192,43),(192,193),(192,196),(192,778),(192,779),(192,780),(192,781),(192,782),(192,783),(192,784),(192,785),(192,786),(192,787),(192,788),(192,789),(192,790),(192,791),(192,792),(192,793),(192,794),(192,795),(192,796),(192,835),(193,48),(193,194),(193,197),(194,1),(194,2),(194,11),(194,13),(194,14),(194,15),(194,16),(194,17),(194,18),(194,19),(194,20),(194,22),(194,23),(194,25),(194,26),(194,27),(194,28),(194,29),(194,30),(194,31),(194,32),(194,33),(194,34),(194,35),(194,36),(194,37),(194,38),(194,39),(194,40),(194,41),(194,44),(194,46),(194,47),(194,51),(194,195),(194,198),(194,632),(194,798),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,200),(196,201),(196,226),(196,227),(196,230),(196,231),(196,233),(196,234),(196,235),(196,238),(196,239),(196,240),(196,241),(196,242),(196,243),(196,244),(196,245),(196,246),(196,247),(196,248),(196,249),(196,250),(196,251),(196,252),(196,253),(196,254),(196,255),(196,256),(196,257),(196,258),(196,259),(196,260),(196,261),(196,262),(196,264),(196,265),(196,266),(196,267),(196,268),(196,269),(196,270),(196,271),(196,272),(196,279),(196,280),(196,283),(196,287),(196,288),(196,289),(196,290),(196,291),(196,292),(196,293),(196,294),(196,295),(196,296),(196,297),(196,298),(196,299),(196,302),(196,303),(196,304),(196,305),(196,306),(196,307),(196,308),(196,309),(196,310),(196,313),(196,314),(196,319),(196,320),(196,321),(196,322),(196,323),(196,324),(196,325),(196,326),(196,327),(196,328),(196,329),(196,330),(196,331),(196,332),(196,333),(196,334),(196,335),(196,336),(196,337),(196,338),(196,339),(196,340),(196,341),(196,342),(196,343),(196,344),(196,345),(196,346),(196,347),(196,348),(196,349),(196,350),(196,351),(196,352),(196,353),(196,354),(196,355),(196,356),(196,357),(196,358),(196,359),(196,360),(196,361),(196,362),(196,363),(196,364),(196,365),(196,366),(196,373),(196,375),(196,400),(196,401),(196,402),(196,403),(196,404),(196,405),(196,406),(196,407),(196,417),(196,418),(196,419),(196,420),(196,421),(196,422),(196,423),(196,424),(196,425),(196,426),(196,427),(196,428),(196,429),(196,434),(196,435),(196,436),(196,437),(196,438),(196,439),(196,440),(196,441),(196,442),(196,443),(196,444),(196,445),(196,446),(196,447),(196,448),(196,449),(196,450),(196,451),(196,452),(196,453),(196,454),(196,455),(196,456),(196,457),(196,458),(196,459),(196,461),(196,463),(196,464),(196,465),(196,472),(196,473),(196,474),(196,475),(196,476),(196,477),(196,478),(196,488),(196,489),(196,491),(196,492),(196,493),(196,495),(196,497),(196,498),(196,499),(196,500),(196,502),(196,503),(196,505),(196,508),(196,511),(196,513),(196,514),(196,516),(196,519),(196,522),(196,523),(196,526),(196,527),(196,529),(196,530),(196,533),(196,535),(196,536),(196,537),(196,538),(196,539),(196,540),(196,541),(196,556),(196,581),(196,582),(196,592),(196,593),(196,596),(196,602),(196,603),(196,604),(196,605),(196,606),(196,607),(196,608),(196,609),(196,610),(196,611),(196,612),(196,613),(196,614),(196,615),(196,616),(196,617),(196,618),(196,619),(196,620),(196,621),(196,622),(196,623),(196,624),(196,625),(196,626),(196,627),(196,628),(196,629),(196,630),(196,631),(196,633),(196,634),(196,635),(196,636),(196,637),(196,638),(196,639),(196,640),(196,641),(196,642),(196,643),(196,644),(196,645),(196,646),(196,647),(196,648),(196,649),(196,650),(196,651),(196,652),(196,653),(196,654),(196,655),(196,656),(196,657),(196,658),(196,659),(196,660),(196,661),(196,662),(196,663),(196,664),(196,665),(196,666),(196,667),(196,668),(196,669),(196,670),(196,671),(196,672),(196,673),(196,674),(196,675),(196,676),(196,677),(196,678),(196,679),(196,680),(196,681),(196,682),(196,683),(196,684),(196,685),(196,686),(196,687),(196,688),(196,689),(196,690),(196,691),(196,692),(196,693),(196,694),(196,695),(196,696),(196,697),(196,698),(196,699),(196,700),(196,701),(196,702),(196,703),(196,704),(196,705),(196,706),(196,707),(196,708),(196,709),(196,710),(196,711),(196,712),(196,713),(196,714),(196,715),(196,716),(196,717),(196,718),(196,719),(196,721),(196,722),(196,723),(196,724),(196,725),(196,726),(196,727),(196,728),(196,729),(196,730),(196,733),(196,734),(196,735),(196,736),(196,738),(196,739),(196,748),(196,753),(196,757),(196,773),(196,777),(197,232),(197,236),(197,237),(197,273),(197,274),(197,275),(197,276),(197,277),(197,284),(197,285),(197,286),(197,301),(197,311),(197,387),(197,388),(197,389),(197,390),(197,391),(197,392),(197,393),(197,394),(197,395),(197,396),(197,397),(197,398),(197,399),(197,479),(197,480),(197,481),(197,482),(197,485),(197,486),(197,487),(197,494),(197,506),(197,509),(197,510),(197,517),(197,518),(197,521),(197,542),(197,543),(197,550),(197,558),(197,568),(197,571),(197,572),(197,573),(197,574),(197,575),(197,576),(197,577),(197,578),(197,579),(197,580),(197,583),(197,584),(197,585),(197,586),(197,587),(197,588),(197,589),(197,590),(197,591),(197,594),(197,595),(197,601),(197,743),(197,750),(197,758),(197,761),(197,762),(197Line truncated
INSERT INTO `rbac_linked_permissions` VALUES (192,21),(192,42),(192,43),(192,193),(192,196),(192,778),(192,779),(192,780),(192,781),(192,782),(192,783),(192,784),(192,785),(192,786),(192,787),(192,788),(192,789),(192,790),(192,791),(192,792),(192,793),(192,794),(192,795),(192,796),(192,835),(193,48),(193,194),(193,197),(194,1),(194,2),(194,11),(194,13),(194,14),(194,15),(194,16),(194,17),(194,18),(194,19),(194,20),(194,22),(194,23),(194,25),(194,26),(194,27),(194,28),(194,29),(194,30),(194,31),(194,32),(194,33),(194,34),(194,35),(194,36),(194,37),(194,38),(194,39),(194,40),(194,41),(194,44),(194,46),(194,47),(194,51),(194,195),(194,198),(194,632),(194,798),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,200),(196,201),(196,226),(196,227),(196,230),(196,231),(196,233),(196,234),(196,235),(196,238),(196,239),(196,240),(196,241),(196,242),(196,243),(196,244),(196,245),(196,246),(196,247),(196,248),(196,249),(196,250),(196,251),(196,252),(196,253),(196,254),(196,255),(196,256),(196,257),(196,258),(196,259),(196,260),(196,261),(196,262),(196,264),(196,265),(196,266),(196,267),(196,268),(196,269),(196,270),(196,271),(196,272),(196,279),(196,280),(196,283),(196,287),(196,288),(196,289),(196,290),(196,291),(196,292),(196,293),(196,294),(196,295),(196,296),(196,297),(196,298),(196,299),(196,302),(196,303),(196,304),(196,305),(196,306),(196,307),(196,308),(196,309),(196,310),(196,313),(196,314),(196,319),(196,320),(196,321),(196,322),(196,323),(196,324),(196,325),(196,326),(196,327),(196,328),(196,329),(196,330),(196,331),(196,332),(196,333),(196,334),(196,335),(196,336),(196,337),(196,338),(196,339),(196,340),(196,341),(196,342),(196,343),(196,344),(196,345),(196,346),(196,347),(196,348),(196,349),(196,350),(196,351),(196,352),(196,353),(196,354),(196,355),(196,356),(196,357),(196,358),(196,359),(196,360),(196,361),(196,362),(196,363),(196,364),(196,365),(196,366),(196,373),(196,375),(196,400),(196,401),(196,402),(196,403),(196,404),(196,405),(196,406),(196,407),(196,417),(196,418),(196,419),(196,420),(196,421),(196,422),(196,423),(196,424),(196,425),(196,426),(196,427),(196,428),(196,429),(196,434),(196,435),(196,436),(196,437),(196,438),(196,439),(196,440),(196,441),(196,442),(196,443),(196,444),(196,445),(196,446),(196,447),(196,448),(196,449),(196,450),(196,451),(196,452),(196,453),(196,454),(196,455),(196,456),(196,457),(196,458),(196,459),(196,461),(196,463),(196,464),(196,465),(196,472),(196,473),(196,474),(196,475),(196,476),(196,477),(196,478),(196,488),(196,489),(196,491),(196,492),(196,493),(196,495),(196,497),(196,498),(196,499),(196,500),(196,502),(196,503),(196,505),(196,508),(196,511),(196,513),(196,514),(196,516),(196,519),(196,522),(196,523),(196,526),(196,527),(196,529),(196,530),(196,533),(196,535),(196,536),(196,537),(196,538),(196,539),(196,540),(196,541),(196,556),(196,581),(196,582),(196,592),(196,593),(196,596),(196,602),(196,603),(196,604),(196,605),(196,606),(196,607),(196,608),(196,609),(196,610),(196,611),(196,612),(196,613),(196,614),(196,615),(196,616),(196,617),(196,618),(196,619),(196,620),(196,621),(196,622),(196,623),(196,624),(196,625),(196,626),(196,627),(196,628),(196,629),(196,630),(196,631),(196,633),(196,634),(196,635),(196,636),(196,637),(196,638),(196,639),(196,640),(196,641),(196,642),(196,643),(196,644),(196,645),(196,646),(196,647),(196,648),(196,649),(196,650),(196,651),(196,652),(196,653),(196,654),(196,655),(196,656),(196,657),(196,658),(196,659),(196,660),(196,661),(196,662),(196,663),(196,664),(196,665),(196,666),(196,667),(196,668),(196,669),(196,670),(196,671),(196,672),(196,673),(196,674),(196,675),(196,676),(196,677),(196,678),(196,679),(196,680),(196,681),(196,682),(196,683),(196,684),(196,685),(196,686),(196,687),(196,688),(196,689),(196,690),(196,691),(196,692),(196,693),(196,694),(196,695),(196,696),(196,697),(196,698),(196,699),(196,700),(196,701),(196,702),(196,703),(196,704),(196,705),(196,706),(196,707),(196,708),(196,709),(196,710),(196,711),(196,712),(196,713),(196,714),(196,715),(196,716),(196,717),(196,718),(196,719),(196,721),(196,722),(196,723),(196,724),(196,725),(196,726),(196,727),(196,728),(196,729),(196,730),(196,733),(196,734),(196,735),(196,736),(196,738),(196,739),(196,748),(196,753),(196,757),(196,773),(196,777),(196,836),(197,232),(197,236),(197,237),(197,273),(197,274),(197,275),(197,276),(197,277),(197,284),(197,285),(197,286),(197,301),(197,311),(197,387),(197,388),(197,389),(197,390),(197,391),(197,392),(197,393),(197,394),(197,395),(197,396),(197,397),(197,398),(197,399),(197,479),(197,480),(197,481),(197,482),(197,485),(197,486),(197,487),(197,494),(197,506),(197,509),(197,510),(197,517),(197,518),(197,521),(197,542),(197,543),(197,550),(197,558),(197,568),(197,571),(197,572),(197,573),(197,574),(197,575),(197,576),(197,577),(197,578),(197,579),(197,580),(197,583),(197,584),(197,585),(197,586),(197,587),(197,588),(197,589),(197,590),(197,591),(197,594),(197,595),(197,601),(197,743),(197,750),(197,758),(197,761),(197Line truncated
/*!40000 ALTER TABLE `rbac_linked_permissions` ENABLE KEYS */;
UNLOCK TABLES;
@@ -399,7 +399,7 @@ CREATE TABLE `rbac_permissions` (
LOCK TABLES `rbac_permissions` WRITE;
/*!40000 ALTER TABLE `rbac_permissions` DISABLE KEYS */;
INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatLine truncated
INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatLine truncated
/*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */;
UNLOCK TABLES;
@@ -486,7 +486,7 @@ CREATE TABLE `updates` (
LOCK TABLES `updates` WRITE;
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','BAF9F6B8F97A30D04BDBBA8127A62A1720F9B904','RELEASED','2015-11-07 15:40:47',0);
INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','BAF9F6B8F97A30D04BDBBA8127A62A1720F9B904','RELEASED','2015-11-07 15:40:47',0),('2015_12_21_boundary.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','RELEASED','2015-12-21 18:37:25',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
+6
View File
@@ -0,0 +1,6 @@
--
DELETE FROM `rbac_permissions` WHERE `id`=836;
INSERT INTO `rbac_permissions` (`id`,`name`) VALUES (836,"Command: .debug boundary");
DELETE FROM `rbac_linked_permissions` WHERE `linkedId`=836;
INSERT INTO `rbac_linked_permissions` (`id`,`linkedId`) VALUES (196, 836);
+10
View File
@@ -0,0 +1,10 @@
--
DELETE FROM `command` WHERE `permission`=836;
INSERT INTO `command` (`name`,`permission`,`help`) VALUES ("debug boundary",836,"Syntax: .debug boundary [fill] [duration]
Flood fills the targeted unit's movement boundary and marks the edge of said boundary with debug creatures.\nSpecify 'fill' as first parameter to fill the entire area with debug creatures.");
DELETE FROM `trinity_string` WHERE `entry` IN (11011,11012,11013);
INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES
(11011,"VisualizeBoundary warning: No interior point of the creature's boundary could be found - check if you have mutually exclusive boundaries!"),
(11012,"VisualizeBoundary error: Creature movement is unbounded"),
(11013,"VisualizeBoundary warning: Reached fail-safe flood boundary - check is your boundary is unbounded!");
+1 -1
View File
@@ -43,7 +43,7 @@ bool GuardAI::CanSeeAlways(WorldObject const* obj)
return false;
}
void GuardAI::EnterEvadeMode()
void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
{
if (!me->IsAlive())
{
+1 -1
View File
@@ -31,7 +31,7 @@ class GuardAI : public ScriptedAI
static int Permissible(Creature const* creature);
bool CanSeeAlways(WorldObject const* obj) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/) override;
void JustDied(Unit* killer) override;
};
#endif
+3 -3
View File
@@ -26,7 +26,7 @@ NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(
void PassiveAI::UpdateAI(uint32)
{
if (me->IsInCombat() && me->getAttackers().empty())
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
}
void PossessedAI::AttackStart(Unit* target)
@@ -64,11 +64,11 @@ void CritterAI::DamageTaken(Unit* /*done_by*/, uint32&)
me->SetControlled(true, UNIT_STATE_FLEEING);
}
void CritterAI::EnterEvadeMode()
void CritterAI::EnterEvadeMode(EvadeReason why)
{
if (me->HasUnitState(UNIT_STATE_FLEEING))
me->SetControlled(false, UNIT_STATE_FLEEING);
CreatureAI::EnterEvadeMode();
CreatureAI::EnterEvadeMode(why);
}
void TriggerAI::IsSummonedBy(Unit* summoner)
+3 -3
View File
@@ -41,7 +41,7 @@ class PossessedAI : public CreatureAI
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit* target) override;
void UpdateAI(uint32) override;
void EnterEvadeMode() override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
void JustDied(Unit*) override;
void KilledUnit(Unit* victim) override;
@@ -57,7 +57,7 @@ class NullCreatureAI : public CreatureAI
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit*) override { }
void UpdateAI(uint32) override { }
void EnterEvadeMode() override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
void OnCharmed(bool /*apply*/) override { }
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
@@ -69,7 +69,7 @@ class CritterAI : public PassiveAI
explicit CritterAI(Creature* c) : PassiveAI(c) { }
void DamageTaken(Unit* done_by, uint32& /*damage*/) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason why) override;
};
class TriggerAI : public NullCreatureAI
+1 -1
View File
@@ -47,7 +47,7 @@ class PetAI : public CreatureAI
//
void MoveInLineOfSight(Unit* /*who*/) override { } // CreatureAI interferes with returning pets
void MoveInLineOfSight_Safe(Unit* /*who*/) { } // CreatureAI interferes with returning pets
void EnterEvadeMode() override { } // For fleeing, pets don't use this type of Evade mechanic
void EnterEvadeMode(EvadeReason /*why*/) override { } // For fleeing, pets don't use this type of Evade mechanic
private:
bool _isVisible(Unit*) const;
+1 -1
View File
@@ -40,7 +40,7 @@ TotemAI::TotemAI(Creature* c) : CreatureAI(c), i_victimGuid()
void TotemAI::MoveInLineOfSight(Unit* /*who*/) { }
void TotemAI::EnterEvadeMode()
void TotemAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->CombatStop(true);
}
+1 -1
View File
@@ -33,7 +33,7 @@ class TotemAI : public CreatureAI
void MoveInLineOfSight(Unit* who) override;
void AttackStart(Unit* victim) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/) override;
void UpdateAI(uint32 diff) override;
static int Permissible(Creature const* creature);
+104 -4
View File
@@ -26,6 +26,7 @@
#include "MapReference.h"
#include "Player.h"
#include "CreatureTextMgr.h"
#include "Language.h"
//Disable CreatureAI when charmed
void CreatureAI::OnCharmed(bool /*apply*/)
@@ -164,9 +165,9 @@ void CreatureAI::TriggerAlert(Unit const* who) const
me->GetMotionMaster()->MoveDistract(5 * IN_MILLISECONDS);
}
void CreatureAI::EnterEvadeMode()
void CreatureAI::EnterEvadeMode(EvadeReason why)
{
if (!_EnterEvadeMode())
if (!_EnterEvadeMode(why))
return;
TC_LOG_DEBUG("entities.unit", "Creature %u enters evade mode.", me->GetEntry());
@@ -241,14 +242,14 @@ bool CreatureAI::UpdateVictim()
}
else if (me->getThreatManager().isThreatListEmpty())
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
return false;
}
return true;
}
bool CreatureAI::_EnterEvadeMode()
bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
{
if (!me->IsAlive())
return false;
@@ -271,6 +272,105 @@ bool CreatureAI::_EnterEvadeMode()
return true;
}
#define BOUNDARY_VISUALIZE_CREATURE 15425
#define BOUNDARY_VISUALIZE_CREATURE_SCALE 0.25f
#define BOUNDARY_VISUALIZE_STEP_SIZE 1
#define BOUNDARY_VISUALIZE_FAILSAFE_LIMIT 750
#define BOUNDARY_VISUALIZE_SPAWN_HEIGHT 5
int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) const
{
typedef std::pair<int32, int32> coordinate;
if (!owner)
return -1;
if (!_boundary || _boundary->empty())
return LANG_CREATURE_MOVEMENT_NOT_BOUNDED;
std::queue<coordinate> Q;
std::unordered_set<coordinate> alreadyChecked;
std::unordered_set<coordinate> outOfBounds;
Position startPosition = owner->GetPosition();
if (!CheckBoundary(&startPosition)) // fall back to creature position
{
startPosition = me->GetPosition();
if (!CheckBoundary(&startPosition))
{
startPosition = me->GetHomePosition();
if (!CheckBoundary(&startPosition)) // fall back to creature home position
return LANG_CREATURE_NO_INTERIOR_POINT_FOUND;
}
}
float spawnZ = startPosition.GetPositionZ() + BOUNDARY_VISUALIZE_SPAWN_HEIGHT;
bool boundsWarning = false;
Q.push({ 0,0 });
while (!Q.empty())
{
coordinate front = Q.front();
bool hasOutOfBoundsNeighbor = false;
for (coordinate off : std::initializer_list<coordinate>{{1,0}, {0,1}, {-1,0}, {0,-1}})
{
coordinate next(front.first + off.first, front.second + off.second);
if (next.first > BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.first < -BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.second > BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.second < -BOUNDARY_VISUALIZE_FAILSAFE_LIMIT)
{
boundsWarning = true;
continue;
}
if (alreadyChecked.find(next) == alreadyChecked.end()) // never check a coordinate twice
{
Position nextPos(startPosition.GetPositionX() + next.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + next.second*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionZ());
if (CheckBoundary(&nextPos))
Q.push(next);
else
{
outOfBounds.insert(next);
hasOutOfBoundsNeighbor = true;
}
alreadyChecked.insert(next);
}
else
if (outOfBounds.find(next) != outOfBounds.end())
hasOutOfBoundsNeighbor = true;
}
if (fill || hasOutOfBoundsNeighbor)
if (TempSummon* point = owner->SummonCreature(BOUNDARY_VISUALIZE_CREATURE, Position(startPosition.GetPositionX() + front.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + front.second*BOUNDARY_VISUALIZE_STEP_SIZE, spawnZ), TEMPSUMMON_TIMED_DESPAWN, duration * IN_MILLISECONDS))
{
point->SetObjectScale(BOUNDARY_VISUALIZE_CREATURE_SCALE);
point->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_STUNNED | UNIT_FLAG_IMMUNE_TO_NPC);
if (!hasOutOfBoundsNeighbor)
point->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
Q.pop();
}
return boundsWarning ? LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED : 0;
}
bool CreatureAI::CheckBoundary(Position* who) const
{
if (!who)
who = me;
if (_boundary)
for (CreatureBoundary::const_iterator it = _boundary->begin(); it != _boundary->end(); ++it)
if (!(*it)->IsWithinBoundary(who))
return false;
return true;
}
bool CreatureAI::CheckInRoom()
{
if (CheckBoundary())
return true;
else
{
EnterEvadeMode(EVADE_REASON_BOUNDARY);
return false;
}
}
Creature* CreatureAI::DoSummon(uint32 entry, const Position& pos, uint32 despawnTime, TempSummonType summonType)
{
return me->SummonCreature(entry, pos, summonType, despawnTime);
+22 -3
View File
@@ -21,6 +21,7 @@
#include "Creature.h"
#include "UnitAI.h"
#include "AreaBoundary.h"
#include "Common.h"
class WorldObject;
@@ -63,6 +64,7 @@ enum SCEquip
EQUIP_UNEQUIP = 0
};
typedef std::set<AreaBoundary const*> CreatureBoundary;
class CreatureAI : public UnitAI
{
protected:
@@ -77,10 +79,20 @@ class CreatureAI : public UnitAI
Creature* DoSummon(uint32 entry, WorldObject* obj, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
bool CheckBoundary(Position* who = nullptr) const;
void SetBoundary(CreatureBoundary const* boundary) { _boundary = boundary; CheckInRoom(); }
public:
enum EvadeReason
{
EVADE_REASON_NO_HOSTILES, // the creature's threat list is empty
EVADE_REASON_BOUNDARY, // the creature has moved outside its evade boundary
EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet
EVADE_REASON_OTHER
};
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr);
explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), m_MoveInLineOfSight_locked(false) { }
explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), _boundary(nullptr), m_MoveInLineOfSight_locked(false) { }
virtual ~CreatureAI() { }
@@ -96,7 +108,7 @@ class CreatureAI : public UnitAI
virtual bool CanRespawn() { return true; }
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode();
virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
virtual void EnterCombat(Unit* /*victim*/) { }
@@ -174,10 +186,17 @@ class CreatureAI : public UnitAI
virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; }
// intended for encounter design/debugging. do not use for other purposes. expensive.
int32 VisualizeBoundary(uint32 duration, Unit* owner=nullptr, bool fill=false) const;
virtual bool CheckInRoom();
CreatureBoundary const* GetBoundary() const { return _boundary; }
protected:
virtual void MoveInLineOfSight(Unit* /*who*/);
bool _EnterEvadeMode();
bool _EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
CreatureBoundary const* _boundary;
private:
bool m_MoveInLineOfSight_locked;
@@ -23,6 +23,7 @@
#include "Cell.h"
#include "CellImpl.h"
#include "ObjectMgr.h"
#include "AreaBoundary.h"
// Spell summary for ScriptedAI::SelectSpell
struct TSpellSummary
@@ -98,7 +99,6 @@ bool SummonList::HasEntry(uint32 entry) const
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
IsFleeing(false),
_evadeCheckCooldown(2500),
_isCombatMovementAllowed(true)
{
_isHeroic = me->GetMap()->IsHeroic();
@@ -405,7 +405,7 @@ enum NPCs
// Hacklike storage used for misc creatures that are expected to evade of outside of a certain area.
// It is assumed the information is found elswehere and can be handled by the core. So far no luck finding such information/way to extract it.
bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff)
/*bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff)
{
if (_evadeCheckCooldown <= diff)
_evadeCheckCooldown = 2500;
@@ -449,15 +449,16 @@ bool ScriptedAI::EnterEvadeIfOutOfCombatArea(uint32 const diff)
EnterEvadeMode();
return true;
}
}*/
// BossAI - for instanced bosses
BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
instance(creature->GetInstanceScript()),
summons(creature),
_boundary(instance ? instance->GetBossBoundary(bossId) : NULL),
_bossId(bossId)
{
if (instance)
SetBoundary(instance->GetBossBoundary(bossId));
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
@@ -494,7 +495,7 @@ void BossAI::_EnterCombat()
// bosses do not respawn, check only on enter combat
if (!instance->CheckRequiredBosses(_bossId))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK);
return;
}
instance->SetBossState(_bossId, IN_PROGRESS);
@@ -518,55 +519,6 @@ void BossAI::TeleportCheaters()
target->NearTeleportTo(x, y, z, 0);
}
bool BossAI::CheckBoundary(Unit* who)
{
if (!GetBoundary() || !who)
return true;
for (BossBoundaryMap::const_iterator itr = GetBoundary()->begin(); itr != GetBoundary()->end(); ++itr)
{
switch (itr->first)
{
case BOUNDARY_N:
if (who->GetPositionX() > itr->second)
return false;
break;
case BOUNDARY_S:
if (who->GetPositionX() < itr->second)
return false;
break;
case BOUNDARY_E:
if (who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_W:
if (who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_NW:
if (who->GetPositionX() + who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SE:
if (who->GetPositionX() + who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_NE:
if (who->GetPositionX() - who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SW:
if (who->GetPositionX() - who->GetPositionY() < itr->second)
return false;
break;
default:
break;
}
}
return true;
}
void BossAI::JustSummoned(Creature* summon)
{
summons.Summon(summon);
@@ -263,8 +263,6 @@ struct ScriptedAI : public CreatureAI
void SetCombatMovement(bool allowMovement);
bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; }
bool EnterEvadeIfOutOfCombatArea(uint32 const diff);
// return true for heroic mode. i.e.
// - for dungeon in mode 10-heroic,
// - for raid in mode 10-Heroic
@@ -332,7 +330,6 @@ struct ScriptedAI : public CreatureAI
private:
Difficulty _difficulty;
uint32 _evadeCheckCooldown;
bool _isCombatMovementAllowed;
bool _isHeroic;
};
@@ -344,7 +341,6 @@ class BossAI : public ScriptedAI
virtual ~BossAI() { }
InstanceScript* const instance;
BossBoundaryMap const* GetBoundary() const { return _boundary; }
void JustSummoned(Creature* summon) override;
void SummonedCreatureDespawn(Creature* summon) override;
@@ -370,16 +366,6 @@ class BossAI : public ScriptedAI
void _JustDied();
void _JustReachedHome() { me->setActive(false); }
virtual bool CheckInRoom()
{
if (CheckBoundary(me))
return true;
EnterEvadeMode();
return false;
}
bool CheckBoundary(Unit* who);
void TeleportCheaters();
EventMap events;
@@ -387,7 +373,6 @@ class BossAI : public ScriptedAI
TaskScheduler scheduler;
private:
BossBoundaryMap const* const _boundary;
uint32 const _bossId;
};
@@ -184,7 +184,7 @@ void npc_escortAI::ReturnToLastPoint()
me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z);
}
void npc_escortAI::EnterEvadeMode()
void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->DeleteThreatList();
@@ -66,7 +66,7 @@ struct npc_escortAI : public ScriptedAI
void ReturnToLastPoint();
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI()
virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc)
@@ -176,7 +176,7 @@ void FollowerAI::JustRespawned()
Reset();
}
void FollowerAI::EnterEvadeMode()
void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->DeleteThreatList();
@@ -46,7 +46,7 @@ class FollowerAI : public ScriptedAI
void MoveInLineOfSight(Unit*) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
void JustDied(Unit*) override;
+1 -1
View File
@@ -408,7 +408,7 @@ void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
MovepointReached(Data);
}
void SmartAI::EnterEvadeMode()
void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
{
if (!me->IsAlive() || me->IsInEvadeMode())
return;
+1 -1
View File
@@ -79,7 +79,7 @@ class SmartAI : public CreatureAI
void EnterCombat(Unit* enemy) override;
// Called for reaction at stopping attack at no attackers or targets
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override;
// Called when the creature is killed
void JustDied(Unit* killer) override;
+1
View File
@@ -696,6 +696,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_MODIFY_XP = 798,
// 799 - 834 6.x only
RBAC_PERM_COMMAND_DEBUG_LOADCELLS = 835,
RBAC_PERM_COMMAND_DEBUG_BOUNDARY = 836,
// custom permissions 1000+
RBAC_PERM_MAX
+12 -1
View File
@@ -180,7 +180,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(),
m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0),
m_lootRecipient(), m_lootRecipientGroup(0), _skinner(), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0),
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(NULL), m_creatureData(NULL), m_waypointID(0), m_path_id(0), m_formation(NULL)
@@ -582,6 +582,17 @@ void Creature::Update(uint32 diff)
LastCharmerGUID.Clear();
}
// periodic check to see if the creature has passed an evade boundary
if (IsAIEnabled && !IsInEvadeMode() && IsInCombat())
{
if (diff >= m_boundaryCheckTime)
{
AI()->CheckInRoom();
m_boundaryCheckTime = 2500;
} else
m_boundaryCheckTime -= diff;
}
// if periodic combat pulse is enabled and we are both in combat and in a dungeon, do this now
if (m_combatPulseDelay > 0 && IsInCombat() && GetMap()->IsDungeon())
{
@@ -698,6 +698,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning
uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance
float m_respawnradius;
uint32 m_boundaryCheckTime; // (msecs) remaining time for next evade boundary check
uint32 m_combatPulseTime; // (msecs) remaining time for next zone-in-combat pulse
uint32 m_combatPulseDelay; // (secs) how often the creature puts the entire zone in combat (only works in dungeons)
+2 -2
View File
@@ -12683,7 +12683,7 @@ void Unit::TauntFadeOut(Unit* taunter)
if (m_ThreatManager.isThreatListEmpty())
{
if (creature->IsAIEnabled)
creature->AI()->EnterEvadeMode();
creature->AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES);
return;
}
@@ -12824,7 +12824,7 @@ Unit* Creature::SelectVictim()
}
// enter in evade mode in other case
AI()->EnterEvadeMode();
AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES);
return NULL;
}
+8 -23
View File
@@ -96,6 +96,13 @@ void InstanceScript::SetHeaders(std::string const& dataHeaders)
headers.push_back(header);
}
void InstanceScript::LoadBossBoundaries(const BossBoundaryData& data)
{
for (BossBoundaryEntry entry : data)
if (entry.bossId < bosses.size())
bosses[entry.bossId].boundary.insert(entry.boundary);
}
void InstanceScript::LoadMinionData(const MinionData* data)
{
while (data->entry)
@@ -113,7 +120,7 @@ void InstanceScript::LoadDoorData(const DoorData* data)
while (data->entry)
{
if (data->bossId < bosses.size())
doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary))));
doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type)));
++data;
}
@@ -236,28 +243,6 @@ void InstanceScript::AddDoor(GameObject* door, bool add)
if (add)
{
data.bossInfo->door[data.type].insert(door->GetGUID());
switch (data.boundary)
{
default:
case BOUNDARY_NONE:
break;
case BOUNDARY_N:
case BOUNDARY_S:
data.bossInfo->boundary[data.boundary] = door->GetPositionX();
break;
case BOUNDARY_E:
case BOUNDARY_W:
data.bossInfo->boundary[data.boundary] = door->GetPositionY();
break;
case BOUNDARY_NW:
case BOUNDARY_SE:
data.bossInfo->boundary[data.boundary] = door->GetPositionX() + door->GetPositionY();
break;
case BOUNDARY_NE:
case BOUNDARY_SW:
data.bossInfo->boundary[data.boundary] = door->GetPositionX() - door->GetPositionY();
break;
}
}
else
data.bossInfo->door[data.type].erase(door->GetGUID());
+14 -25
View File
@@ -19,9 +19,11 @@
#ifndef TRINITY_INSTANCE_DATA_H
#define TRINITY_INSTANCE_DATA_H
#include <set>
#include "ZoneScript.h"
#include "World.h"
#include "ObjectMgr.h"
#include "CreatureAI.h"
#define OUT_SAVE_INST_DATA TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_SAVE_INST_DATA_COMPLETE TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
@@ -65,32 +67,19 @@ enum DoorType
MAX_DOOR_TYPES
};
enum BoundaryType
{
BOUNDARY_NONE = 0,
BOUNDARY_N,
BOUNDARY_S,
BOUNDARY_E,
BOUNDARY_W,
BOUNDARY_NE,
BOUNDARY_NW,
BOUNDARY_SE,
BOUNDARY_SW,
BOUNDARY_MAX_X = BOUNDARY_N,
BOUNDARY_MIN_X = BOUNDARY_S,
BOUNDARY_MAX_Y = BOUNDARY_W,
BOUNDARY_MIN_Y = BOUNDARY_E
};
typedef std::map<BoundaryType, float> BossBoundaryMap;
struct DoorData
{
uint32 entry, bossId;
DoorType type;
uint32 boundary;
};
struct BossBoundaryEntry
{
uint32 const bossId;
AreaBoundary const* const boundary;
};
typedef std::list<BossBoundaryEntry> BossBoundaryData;
struct MinionData
{
uint32 entry, bossId;
@@ -108,16 +97,15 @@ struct BossInfo
EncounterState state;
GuidSet door[MAX_DOOR_TYPES];
GuidSet minion;
BossBoundaryMap boundary;
CreatureBoundary boundary;
};
struct DoorInfo
{
explicit DoorInfo(BossInfo* _bossInfo, DoorType _type, BoundaryType _boundary)
: bossInfo(_bossInfo), type(_type), boundary(_boundary) { }
explicit DoorInfo(BossInfo* _bossInfo, DoorType _type)
: bossInfo(_bossInfo), type(_type) { }
BossInfo* bossInfo;
DoorType type;
BoundaryType boundary;
};
struct MinionInfo
@@ -221,7 +209,7 @@ class InstanceScript : public ZoneScript
virtual bool SetBossState(uint32 id, EncounterState state);
EncounterState GetBossState(uint32 id) const { return id < bosses.size() ? bosses[id].state : TO_BE_DECIDED; }
static std::string GetBossStateName(uint8 state);
BossBoundaryMap const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : NULL; }
CreatureBoundary const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : NULL; }
// Achievement criteria additional requirements check
// NOTE: not use this if same can be checked existed requirement types from AchievementCriteriaRequirementType
@@ -248,6 +236,7 @@ class InstanceScript : public ZoneScript
protected:
void SetHeaders(std::string const& dataHeaders);
void SetBossNumber(uint32 number) { bosses.resize(number); }
void LoadBossBoundaries(BossBoundaryData const& data);
void LoadDoorData(DoorData const* data);
void LoadMinionData(MinionData const* data);
void LoadObjectData(ObjectData const* creatureData, ObjectData const* gameObjectData);
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (C) 2015-2016 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AreaBoundary.h"
#include "Unit.h"
#include "TemporarySummon.h"
// ---== RECTANGLE ==---
RectangleBoundary::RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_RECTANGLE, isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { }
bool RectangleBoundary::IsWithinBoundaryArea(const Position* pos) const
{
if (!pos)
return false;
return !(
pos->GetPositionX() < _minX ||
pos->GetPositionX() > _maxX ||
pos->GetPositionY() < _minY ||
pos->GetPositionY() > _maxY
);
}
// ---== CIRCLE ==---
CircleBoundary::CircleBoundary(Position const& center, double radius, bool isInverted) :
CircleBoundary(DoublePosition(center), radius, isInverted) { }
CircleBoundary::CircleBoundary(DoublePosition const& center, double radius, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(radius*radius) { }
CircleBoundary::CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted) :
CircleBoundary(DoublePosition(center), DoublePosition(pointOnCircle), isInverted) { }
CircleBoundary::CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(center.GetDoubleExactDist2dSq(pointOnCircle)) { }
bool CircleBoundary::IsWithinBoundaryArea(const Position* pos) const
{
if (!pos)
return false;
double offX = _center.GetDoublePositionX() - pos->GetPositionX();
double offY = _center.GetDoublePositionY() - pos->GetPositionY();
return offX*offX+offY*offY <= _radiusSq;
}
// ---== ELLIPSE ==---
EllipseBoundary::EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted) :
EllipseBoundary(DoublePosition(center), radiusX, radiusY, isInverted) { }
EllipseBoundary::EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_ELLIPSE, isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { }
bool EllipseBoundary::IsWithinBoundaryArea(const Position* pos) const
{
if (!pos)
return false;
double offX = _center.GetDoublePositionX()-pos->GetPositionX(), offY = _center.GetDoublePositionY()-pos->GetPositionY();
return (offX*offX)*_scaleXSq + (offY*offY) <= _radiusYSq;
}
// ---== TRIANGLE ==---
TriangleBoundary::TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted) :
TriangleBoundary(DoublePosition(pointA), DoublePosition(pointB), DoublePosition(pointC), isInverted) { }
TriangleBoundary::TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_TRIANGLE, isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { }
bool TriangleBoundary::IsWithinBoundaryArea(const Position* pos) const
{
if (!pos)
return false;
// half-plane signs
bool sign1 = ((-_b.GetDoublePositionX() + pos->GetPositionX()) * _aby - (-_b.GetDoublePositionY() + pos->GetPositionY()) * _abx) < 0;
bool sign2 = ((-_c.GetDoublePositionX() + pos->GetPositionX()) * _bcy - (-_c.GetDoublePositionY() + pos->GetPositionY()) * _bcx) < 0;
bool sign3 = ((-_a.GetDoublePositionX() + pos->GetPositionX()) * _cay - (-_a.GetDoublePositionY() + pos->GetPositionY()) * _cax) < 0;
// if all signs are the same, the point is inside the triangle
return ((sign1 == sign2) && (sign2 == sign3));
}
// ---== PARALLELOGRAM ==---
ParallelogramBoundary::ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted) :
ParallelogramBoundary(DoublePosition(cornerA), DoublePosition(cornerB), DoublePosition(cornerD), isInverted) { }
ParallelogramBoundary::ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_PARALLELOGRAM, isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { }
bool ParallelogramBoundary::IsWithinBoundaryArea(const Position* pos) const
{
if (!pos)
return false;
// half-plane signs
bool sign1 = ((-_b.GetDoublePositionX() + pos->GetPositionX()) * _aby - (-_b.GetDoublePositionY() + pos->GetPositionY()) * _abx) < 0;
bool sign2 = ((-_a.GetDoublePositionX() + pos->GetPositionX()) * _day - (-_a.GetDoublePositionY() + pos->GetPositionY()) * _dax) < 0;
bool sign3 = ((-_d.GetDoublePositionY() + pos->GetPositionY()) * _abx - (-_d.GetDoublePositionX() + pos->GetPositionX()) * _aby) < 0; // AB = -CD
bool sign4 = ((-_c.GetDoublePositionY() + pos->GetPositionY()) * _dax - (-_c.GetDoublePositionX() + pos->GetPositionX()) * _day) < 0; // DA = -BC
// if all signs are equal, the point is inside
return ((sign1 == sign2) && (sign2 == sign3) && (sign3 == sign4));
}
// ---== Z RANGE ==---
ZRangeBoundary::ZRangeBoundary(float minZ, float maxZ, bool isInverted) :
AreaBoundary(BoundaryType::BOUNDARY_Z_RANGE, isInverted), _minZ(minZ), _maxZ(maxZ) { }
bool ZRangeBoundary::IsWithinBoundaryArea(const Position* pos) const
{
if (!pos)
return false;
return !(pos->GetPositionZ() < _minZ || pos->GetPositionZ() > _maxZ);
}
+152
View File
@@ -0,0 +1,152 @@
/*
* Copyright (C) 2015-2016 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_AREA_BOUNDARY_H
#define TRINITY_AREA_BOUNDARY_H
#include "Position.h"
class AreaBoundary
{
public:
enum BoundaryType
{
BOUNDARY_RECTANGLE, // Rectangle aligned with the coordinate axis
BOUNDARY_CIRCLE,
BOUNDARY_ELLIPSE,
BOUNDARY_TRIANGLE,
BOUNDARY_PARALLELOGRAM,
BOUNDARY_Z_RANGE,
};
BoundaryType GetBoundaryType() const { return m_boundaryType; }
bool IsWithinBoundary(const Position* pos) const { return (IsWithinBoundaryArea(pos) != m_isInvertedBoundary); }
struct DoublePosition : Position
{
double d_positionX, d_positionY, d_positionZ;
DoublePosition(double x = 0, double y = 0, double z = 0, float o = 0)
: Position((float)x, (float)y, (float)z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { }
DoublePosition(float x = 0, float y = 0, float z = 0, float o = 0)
: Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { }
DoublePosition(const Position& pos)
: DoublePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()) { }
double GetDoublePositionX() const { return d_positionX; }
double GetDoublePositionY() const { return d_positionY; }
double GetDoublePositionZ() const { return d_positionZ; }
double GetDoubleExactDist2dSq(DoublePosition const& pos) const {
double offX = GetDoublePositionX() - pos.GetDoublePositionX();
double offY = GetDoublePositionY() - pos.GetDoublePositionY();
return (offX*offX) + (offY*offY);
}
Position* sync() { m_positionX = (float)d_positionX; m_positionY = (float)d_positionY; m_positionZ = (float)d_positionZ; return this; }
};
protected:
AreaBoundary(BoundaryType bType, bool isInverted) : m_boundaryType(bType), m_isInvertedBoundary(isInverted) { }
virtual bool IsWithinBoundaryArea(const Position* pos) const = 0;
const BoundaryType m_boundaryType;
bool m_isInvertedBoundary;
};
class RectangleBoundary : public AreaBoundary
{
public:
// X axis is north/south, Y axis is east/west, larger values are northwest
RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(const Position* pos) const override;
private:
const float _minX, _maxX, _minY, _maxY;
};
class CircleBoundary : public AreaBoundary
{
public:
CircleBoundary(Position const& center, double radius, bool isInverted = false);
CircleBoundary(DoublePosition const& center, double radius, bool isInverted = false);
CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted = false);
CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(const Position* pos) const override;
private:
const DoublePosition _center;
const double _radiusSq;
};
class EllipseBoundary : public AreaBoundary
{
public:
EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted = false);
EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(const Position* pos) const override;
private:
const DoublePosition _center;
const double _radiusYSq, _scaleXSq;
};
class TriangleBoundary : public AreaBoundary
{
public:
TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted = false);
TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(const Position* pos) const override;
private:
const DoublePosition _a, _b, _c;
const double _abx, _bcx, _cax, _aby, _bcy, _cay;
};
class ParallelogramBoundary : public AreaBoundary
{
public:
// Note: AB must be orthogonal to AD
ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted = false);
ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(const Position* pos) const override;
private:
const DoublePosition _a, _b, _d, _c;
const double _abx, _dax, _aby, _day;
};
class ZRangeBoundary : public AreaBoundary
{
public:
ZRangeBoundary(float minZ, float maxZ, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(const Position* pos) const override;
private:
const float _minZ, _maxZ;
};
#endif //TRINITY_AREA_BOUNDARY_H
+3
View File
@@ -1205,6 +1205,9 @@ enum TrinityStrings
LANG_NPCINFO_FLAGS_EXTRA = 11009,
LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION = 11010,
LANG_CREATURE_NO_INTERIOR_POINT_FOUND = 11011,
LANG_CREATURE_MOVEMENT_NOT_BOUNDED = 11012,
LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED = 11013,
LANG_INSTANCE_BIND_MISMATCH = 11014
};
#endif
+1
View File
@@ -25,6 +25,7 @@ set(scripts_STAT_SRCS
../game/AI/ScriptedAI/ScriptedEscortAI.cpp
../game/AI/ScriptedAI/ScriptedCreature.cpp
../game/AI/ScriptedAI/ScriptedFollowerAI.cpp
../game/Maps/AreaBoundary.cpp
)
if(SCRIPTS)
+28
View File
@@ -93,6 +93,7 @@ public:
{ "moveflags", rbac::RBAC_PERM_COMMAND_DEBUG_MOVEFLAGS, false, &HandleDebugMoveflagsCommand, "" },
{ "transport", rbac::RBAC_PERM_COMMAND_DEBUG_TRANSPORT, false, &HandleDebugTransportCommand, "" },
{ "loadcells", rbac::RBAC_PERM_COMMAND_DEBUG_LOADCELLS, false, &HandleDebugLoadCellsCommand, "" },
{ "boundary", rbac::RBAC_PERM_COMMAND_DEBUG_BOUNDARY, false, &HandleDebugBoundaryCommand, "" }
};
static std::vector<ChatCommand> commandTable =
{
@@ -1414,6 +1415,33 @@ public:
handler->PSendSysMessage("Cells loaded (mapId: %u) After load - Next GameObject %u, Creature %u", map->GetId(), map->GetMaxLowGuid<HighGuid::GameObject>(), map->GetMaxLowGuid<HighGuid::Unit>());
return true;
}
static bool HandleDebugBoundaryCommand(ChatHandler* handler, char const* args)
{
Player* player = handler->GetSession()->GetPlayer();
if (!player)
return false;
Creature* target = handler->getSelectedCreature();
if (!target || !target->IsAIEnabled || !target->AI())
{
return false;
}
char* fill_str = args ? strtok((char*)args, " ") : nullptr;
char* duration_str = args ? strtok(nullptr, " ") : nullptr;
int duration = duration_str ? atoi(duration_str) : -1;
if (duration <= 0 || duration >= 30 * MINUTE) // arbitary upper limit
duration = 3 * MINUTE;
bool doFill = fill_str ? (stricmp(fill_str, "FILL") == 0) : false;
int32 errMsg = target->AI()->VisualizeBoundary(duration, player, doFill);
if (errMsg > 0)
handler->PSendSysMessage(errMsg);
return true;
}
};
void AddSC_debug_commandscript()
@@ -198,9 +198,9 @@ class boss_doomrel : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
_instance->SetGuidData(DATA_EVENSTARTER, ObjectGuid::Empty);
}
@@ -22,14 +22,14 @@
DoorData const doorData[] =
{
{ GO_BOSSGATE01, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_DRAKE_RIDER_PORTCULLIS, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ALTERAC_VALLEY_GATE, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GATE, DATA_FIREMAW, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GATE, DATA_EBONROC, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GATE, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_VACCUUM_EXIT_GATE, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_BOSSGATE01, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE },
{ GO_DRAKE_RIDER_PORTCULLIS, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE },
{ GO_ALTERAC_VALLEY_GATE, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE },
{ GO_GATE, DATA_FIREMAW, DOOR_TYPE_PASSAGE },
{ GO_GATE, DATA_EBONROC, DOOR_TYPE_PASSAGE },
{ GO_GATE, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE },
{ GO_VACCUUM_EXIT_GATE, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const creatureData[] =
@@ -91,9 +91,9 @@ public:
Initialize();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
ResetTimer = 2000;
}
@@ -28,12 +28,12 @@
DoorData const doorData[] =
{
{ GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE },
{ GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM },
{ GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE },
{ GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE },
{ GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_magisters_terrace : public InstanceMapScript
@@ -596,10 +596,10 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (!bIsBattle)//do not reset self if we are in battle
npc_escortAI::EnterEvadeMode();
npc_escortAI::EnterEvadeMode(why);
}
void UpdateAI(uint32 diff) override
@@ -21,8 +21,8 @@
DoorData const doorData[] =
{
{ GO_HIGH_INQUISITORS_DOOR, DATA_MOGRAINE_AND_WHITE_EVENT, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_HIGH_INQUISITORS_DOOR, DATA_MOGRAINE_AND_WHITE_EVENT, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_scarlet_monastery : public InstanceMapScript
@@ -108,7 +108,7 @@ class boss_kirtonos_the_herald : public CreatureScript
_JustDied();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GATE_KIRTONOS)))
gate->SetGoState(GO_STATE_ACTIVE);
@@ -136,10 +136,10 @@ public:
me->SummonCreature(NPC_FELMYST, x, y, z + 30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (!Intro)
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void StartIntro()
@@ -169,12 +169,12 @@ public:
me->SetFullHealth(); //dunno why it does not resets health at evade..
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
bJustReset = true;
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void DoAction(int32 param) override
@@ -237,7 +237,7 @@ public:
{
if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75)
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_BOUNDARY);
return;
}
if (HealthBelowPct(10) && !isEnraged)
@@ -261,7 +261,7 @@ public:
else
{
TC_LOG_ERROR("scripts", "Didn't find Shathrowar. Kalecgos event reseted.");
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
}
@@ -423,7 +423,7 @@ public:
TalkTimer = 15000;
break;
case 3:
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
break;
default:
break;
@@ -624,9 +624,9 @@ public:
Talk(SAY_KJ_SLAY);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
summons.DespawnAll();
@@ -151,7 +151,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU)))
muru->AI()->Reset(); // Reset encounter.
@@ -31,13 +31,13 @@
DoorData const doorData[] =
{
{ GO_FIRE_BARRIER, DATA_FELMYST, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_MURUS_GATE_1, DATA_MURU, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_MURUS_GATE_2, DATA_MURU, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_BOSS_COLLISION_1, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_BOSS_COLLISION_2, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_FORCE_FIELD, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_FIRE_BARRIER, DATA_FELMYST, DOOR_TYPE_PASSAGE },
{ GO_MURUS_GATE_1, DATA_MURU, DOOR_TYPE_ROOM },
{ GO_MURUS_GATE_2, DATA_MURU, DOOR_TYPE_PASSAGE },
{ GO_BOSS_COLLISION_1, DATA_KALECGOS, DOOR_TYPE_ROOM },
{ GO_BOSS_COLLISION_2, DATA_KALECGOS, DOOR_TYPE_ROOM },
{ GO_FORCE_FIELD, DATA_KALECGOS, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_sunwell_plateau : public InstanceMapScript
@@ -424,8 +424,6 @@ class boss_janalai : public CreatureScript
} else HatcherTimer -= diff;
}
EnterEvadeIfOutOfCombatArea(diff);
DoMeleeAttackIfReady();
if (FireBreathTimer <= diff)
@@ -157,9 +157,9 @@ class boss_arlokk : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
if (GameObject* object = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_GONG_OF_BETHEKK)))
object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
me->DespawnOrUnsummon(4000);
@@ -29,8 +29,8 @@ EndScriptData */
DoorData const doorData[] =
{
{ GO_FORCEFIELD, DATA_ARLOKK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_FORCEFIELD, DATA_ARLOKK, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_zulgurub : public InstanceMapScript
@@ -256,7 +256,7 @@ public:
Initialize();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DisappearAndDie();
@@ -417,7 +417,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DisappearAndDie();
@@ -417,7 +417,7 @@ void hyjalAI::Reset()
}
}
void hyjalAI::EnterEvadeMode()
void hyjalAI::EnterEvadeMode(EvadeReason /*why*/)
{
if (me->GetEntry() != JAINA)
me->RemoveAllAuras();
@@ -123,7 +123,7 @@ struct hyjalAI : public npc_escortAI
void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat
void EnterEvadeMode(); // Send creature back to spawn location and evade.
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER); // Send creature back to spawn location and evade.
void EnterCombat(Unit* /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack
@@ -43,9 +43,9 @@ Position const GuardianOfTimePos = { 2321.489f, 1268.383f, 132.8507f, 0.418879f
DoorData const doorData[] =
{
{ GO_MALGANIS_GATE_2, DATA_MAL_GANIS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_EXIT_GATE, DATA_MAL_GANIS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_MALGANIS_GATE_2, DATA_MAL_GANIS, DOOR_TYPE_ROOM },
{ GO_EXIT_GATE, DATA_MAL_GANIS, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_culling_of_stratholme : public InstanceMapScript
@@ -316,20 +316,9 @@ public:
MovePoint = iTemp;
}
bool CheckInRoom() override
{
if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 95.0f)
{
EnterEvadeMode();
return false;
}
return true;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
//Common to PHASE_START && PHASE_END
@@ -31,6 +31,11 @@ EndScriptData */
#include "onyxias_lair.h"
#include "TemporarySummon.h"
BossBoundaryData const boundaries =
{
{ DATA_ONYXIA, new CircleBoundary(Position(-34.3697f, -212.3296f), 100.0) }
};
class instance_onyxias_lair : public InstanceMapScript
{
public:
@@ -47,6 +52,7 @@ public:
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
onyxiaLiftoffTimer = 0;
manyWhelpsCounter = 0;
@@ -129,10 +129,10 @@ class boss_ayamiss : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
me->ClearUnitState(UNIT_STATE_ROOT);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void EnterCombat(Unit* attacker) override
@@ -72,9 +72,9 @@ class boss_buru : public CreatureScript
_phase = 0;
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
for (ObjectGuid eggGuid : Eggs)
if (Creature* egg = me->GetMap()->GetCreature(eggGuid))
@@ -163,11 +163,11 @@ class boss_ossirian : public CreatureScript
Talk(SAY_SLAY);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
Cleanup();
summons.DespawnAll();
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
@@ -77,9 +77,9 @@ class boss_skeram : public CreatureScript
Talk(SAY_SLAY);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
if (me->IsSummon())
((TempSummon*)me)->UnSummon();
}
@@ -190,10 +190,10 @@ class boss_viscidus : public CreatureScript
events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
summons.DespawnAll();
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
@@ -304,7 +304,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
if (player && player->IsInCombat() && player->getAttackerForHelper())
@@ -312,7 +312,7 @@ public:
AttackStart(player->getAttackerForHelper());
return;
}
npc_escortAI::EnterEvadeMode();
npc_escortAI::EnterEvadeMode(why);
}
void StartEvent(Player* player)
@@ -22,8 +22,8 @@
DoorData const doorData[] =
{
{ GO_PRINCE_TALDARAM_GATE, DATA_PRINCE_TALDARAM, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_PRINCE_TALDARAM_GATE, DATA_PRINCE_TALDARAM, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_ahnkahet : public InstanceMapScript
@@ -21,11 +21,11 @@
DoorData const doorData[] =
{
{ GO_KRIKTHIR_DOOR, DATA_KRIKTHIR_THE_GATEWATCHER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ANUBARAK_DOOR_1, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ANUBARAK_DOOR_2, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ANUBARAK_DOOR_3, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_KRIKTHIR_DOOR, DATA_KRIKTHIR_THE_GATEWATCHER, DOOR_TYPE_PASSAGE },
{ GO_ANUBARAK_DOOR_1, DATA_ANUBARAK, DOOR_TYPE_ROOM },
{ GO_ANUBARAK_DOOR_2, DATA_ANUBARAK, DOOR_TYPE_ROOM },
{ GO_ANUBARAK_DOOR_3, DATA_ANUBARAK, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const creatureData[] =
@@ -501,8 +501,6 @@ public:
}
DoMeleeAttackIfReady();
EnterEvadeIfOutOfCombatArea(diff);
}
private:
@@ -23,6 +23,11 @@
0 - Sartharion
*/
BossBoundaryData const boundaries =
{
{ DATA_SARTHARION, new RectangleBoundary(3218.86f, 3275.69f, 484.68f, 572.4f) }
};
class instance_obsidian_sanctum : public InstanceMapScript
{
public:
@@ -33,6 +38,8 @@ public:
instance_obsidian_sanctum_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
}
void OnCreatureCreate(Creature* creature) override
@@ -98,7 +98,7 @@ class boss_general_zarithrian : public CreatureScript
{
_Reset();
if (instance->GetBossState(DATA_SAVIANA_RAGEFIRE) == DONE && instance->GetBossState(DATA_BALTHARUS_THE_WARBORN) == DONE)
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
}
void EnterCombat(Unit* /*who*/) override
@@ -145,13 +145,6 @@ class boss_general_zarithrian : public CreatureScript
if (!UpdateVictim())
return;
// Can't use room boundary here, the gameobject is spawned at the same position as the boss. This is just as good anyway.
if (me->GetPositionX() > 3058.0f)
{
EnterEvadeMode();
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
@@ -228,7 +221,7 @@ class npc_onyx_flamecaller : public CreatureScript
_events.ScheduleEvent(EVENT_LAVA_GOUT, 5000);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
// Prevent EvadeMode
}
@@ -257,21 +257,9 @@ struct generic_halionAI : public BossAI
}
}
bool CheckInRoom() override
{
// Rough radius, it is not an exactly perfect circle
if (me->GetDistance2d(HalionControllerSpawnPos.GetPositionX(), HalionControllerSpawnPos.GetPositionY()) > 48.5f)
{
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->EnterEvadeMode();
return false;
}
return true;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom() || me->HasUnitState(UNIT_STATE_CASTING))
if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
return;
events.Update(diff);
@@ -324,11 +312,15 @@ class boss_halion : public CreatureScript
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if(why == EVADE_REASON_BOUNDARY)
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->EnterEvadeMode();
// Phase 1: We always can evade. Phase 2 & 3: We can evade if and only if the controller tells us to.
if (events.IsInPhase(PHASE_ONE) || _canEvade)
generic_halionAI::EnterEvadeMode();
generic_halionAI::EnterEvadeMode(why);
}
void EnterCombat(Unit* who) override
@@ -498,7 +490,7 @@ class boss_twilight_halion : public CreatureScript
}
// Never evade
void EnterEvadeMode() override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
void KilledUnit(Unit* victim) override
{
@@ -1023,7 +1015,7 @@ class npc_meteor_strike_initial : public CreatureScript
}
void UpdateAI(uint32 /*diff*/) override { }
void EnterEvadeMode() override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
private:
InstanceScript* _instance;
std::list<Creature*> _meteorList;
@@ -1149,7 +1141,7 @@ class npc_meteor_strike_flame : public CreatureScript
flame->AI()->SetGUID(_rootOwnerGuid);
}
void EnterEvadeMode() override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
private:
InstanceScript* _instance;
@@ -23,10 +23,16 @@
#include "WorldPacket.h"
#include "ruby_sanctum.h"
BossBoundaryData const boundaries =
{
{ DATA_GENERAL_ZARITHRIAN, new EllipseBoundary(Position(3013.409f, 529.492f), 45.0, 100.0) },
{ DATA_HALION, new CircleBoundary(Position(3156.037f, 533.2656f), 48.5) }
};
DoorData const doorData[] =
{
{GO_FIRE_FIELD, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE},
{GO_FIRE_FIELD, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE },
{0, 0, DOOR_TYPE_ROOM },
};
class instance_ruby_sanctum : public InstanceMapScript
@@ -40,6 +46,7 @@ class instance_ruby_sanctum : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
BaltharusSharedHealth = 0;
}
@@ -167,10 +167,10 @@ class boss_gormok : public CreatureScript
summons.DespawnAll();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void MovementInform(uint32 type, uint32 pointId) override
@@ -309,11 +309,6 @@ class npc_snobold_vassal : public CreatureScript
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
}
void EnterEvadeMode() override
{
ScriptedAI::EnterEvadeMode();
}
void EnterCombat(Unit* who) override
{
_targetGUID = who->GetGUID();
@@ -751,10 +746,10 @@ class boss_dreadscale : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
boss_jormungarAI::EnterEvadeMode();
boss_jormungarAI::EnterEvadeMode(why);
}
void JustReachedHome() override
@@ -924,10 +919,10 @@ class boss_icehowl : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void JustReachedHome() override
@@ -416,10 +416,10 @@ class boss_fjola : public CreatureScript
boss_twin_baseAI::EnterCombat(who);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
boss_twin_baseAI::EnterEvadeMode();
boss_twin_baseAI::EnterEvadeMode(why);
}
void JustReachedHome() override
@@ -22,6 +22,15 @@
#include "Player.h"
#include "TemporarySummon.h"
AreaBoundary const* const mainBoundary = new CircleBoundary(Position(563.26f, 139.6f), 75.0);
BossBoundaryData const boundaries = {
{ BOSS_BEASTS, mainBoundary },
{ BOSS_JARAXXUS, mainBoundary },
{ BOSS_CRUSADERS, mainBoundary },
{ BOSS_VALKIRIES, mainBoundary },
{ BOSS_ANUBARAK, new EllipseBoundary(Position(746.0f, 135.0f), 100.0, 75.0) }
};
class instance_trial_of_the_crusader : public InstanceMapScript
{
public:
@@ -33,6 +42,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTERS);
LoadBossBoundaries(boundaries);
TrialCounter = 50;
EventStage = 0;
NorthrendBeasts = NOT_STARTED;
@@ -1269,7 +1269,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (_despawn)
return;
@@ -1335,7 +1335,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript
}
else if (me->getThreatManager().getThreatList().size() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return false;
}
@@ -1438,7 +1438,7 @@ struct npc_gauntlet_trash : public ScriptedAI
_events.Reset();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (_instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
_instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
@@ -1546,10 +1546,10 @@ class npc_phantom_mage : public CreatureScript
{
npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature) { }
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (!me->HasAura(AURA_HALLUCINATION))
npc_gauntlet_trash::EnterEvadeMode();
npc_gauntlet_trash::EnterEvadeMode(why);
}
void EnterCombat(Unit* /*who*/) override
@@ -1626,10 +1626,10 @@ class npc_phantom_hallucination : public CreatureScript
DoZoneInCombat(me, 150.0f);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (me->GetOwner() && !me->GetOwner()->HasAura(AURA_HALLUCINATION))
npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode();
npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
@@ -166,10 +166,10 @@ class boss_ick : public CreatureScript
events.ScheduleEvent(EVENT_SPECIAL, urand(30000, 35000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
me->GetMotionMaster()->Clear();
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
@@ -203,7 +203,7 @@ class boss_ick : public CreatureScript
if (!me->GetVictim() && me->getThreatManager().isThreatListEmpty())
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
return;
}
@@ -170,7 +170,7 @@ class boss_tyrannus : public CreatureScript
me->GetMotionMaster()->MoveChase(victim);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
instance->SetBossState(DATA_TYRANNUS, FAIL);
if (Creature* rimefang = GetRimefang())
@@ -27,9 +27,9 @@ Position const EventLeaderPos2 = {1054.368f, 107.14620f, 628.4467f, 0.0f};
DoorData const Doors[] =
{
{GO_ICE_WALL, DATA_GARFROST, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ICE_WALL, DATA_ICK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_HALLS_OF_REFLECTION_PORTCULLIS, DATA_TYRANNUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ICE_WALL, DATA_GARFROST, DOOR_TYPE_PASSAGE },
{GO_ICE_WALL, DATA_ICK, DOOR_TYPE_PASSAGE },
{GO_HALLS_OF_REFLECTION_PORTCULLIS, DATA_TYRANNUS, DOOR_TYPE_PASSAGE },
};
class instance_pit_of_saron : public InstanceMapScript
@@ -336,7 +336,7 @@ class boss_drakkari_elemental : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DespawnOrUnsummon();
}
@@ -23,12 +23,12 @@
DoorData const doorData[] =
{
{ GO_GAL_DARAH_DOOR_1, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GAL_DARAH_DOOR_2, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GAL_DARAH_DOOR_3, DATA_GAL_DARAH, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ECK_THE_FEROCIOUS_DOOR, DATA_MOORABI, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ECK_THE_FEROCIOUS_DOOR_BEHIND, DATA_ECK_THE_FEROCIOUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_GAL_DARAH_DOOR_1, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE },
{ GO_GAL_DARAH_DOOR_2, DATA_GAL_DARAH, DOOR_TYPE_PASSAGE },
{ GO_GAL_DARAH_DOOR_3, DATA_GAL_DARAH, DOOR_TYPE_ROOM },
{ GO_ECK_THE_FEROCIOUS_DOOR, DATA_MOORABI, DOOR_TYPE_PASSAGE },
{ GO_ECK_THE_FEROCIOUS_DOOR_BEHIND, DATA_ECK_THE_FEROCIOUS, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const creatureData[] =
@@ -173,7 +173,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
{
if (!instance->CheckRequiredBosses(DATA_BLOOD_QUEEN_LANA_THEL, who->ToPlayer()))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
return;
}
@@ -244,9 +244,11 @@ class boss_blood_queen_lana_thel : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
_EnterEvadeMode();
if (!_EnterEvadeMode(why))
return;
CleanAuras();
if (_killMinchar)
{
@@ -257,6 +259,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
}
else
{
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
Reset();
}
@@ -333,7 +336,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -287,7 +287,7 @@ class boss_deathbringer_saurfang : public CreatureScript
if (!instance->CheckRequiredBosses(DATA_DEATHBRINGER_SAURFANG, who->ToPlayer()))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
return;
}
@@ -332,9 +332,9 @@ class boss_deathbringer_saurfang : public CreatureScript
ScriptedAI::AttackStart(victim);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
if (_introDone)
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
}
@@ -390,7 +390,7 @@ class boss_deathbringer_saurfang : public CreatureScript
if (target->GetTransport())
{
summon->DespawnOrUnsummon(1);
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
@@ -420,7 +420,7 @@ class boss_deathbringer_saurfang : public CreatureScript
{
if (target->GetTransport())
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
@@ -115,7 +115,7 @@ class boss_festergut : public CreatureScript
{
if (!instance->CheckRequiredBosses(DATA_FESTERGUT, who->ToPlayer()))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
return;
}
@@ -145,9 +145,9 @@ class boss_festergut : public CreatureScript
instance->SetBossState(DATA_FESTERGUT, FAIL);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
if (Creature* professor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PROFESSOR_PUTRICIDE)))
professor->AI()->EnterEvadeMode();
}
@@ -166,7 +166,7 @@ class boss_festergut : public CreatureScript
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -572,7 +572,7 @@ struct gunship_npc_AI : public ScriptedAI
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (!me->IsAlive() || !me->IsInCombat())
return;
@@ -621,7 +621,7 @@ protected:
{
if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return false;
}
@@ -634,7 +634,7 @@ protected:
}
else if (me->getThreatManager().isThreatListEmpty())
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return false;
}
@@ -875,7 +875,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript
_events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (!me->IsAlive())
return;
@@ -1143,7 +1143,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript
_events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (!me->IsAlive())
return;
@@ -1721,9 +1721,9 @@ class npc_gunship_mage : public CreatureScript
me->SetReactState(REACT_PASSIVE);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void MovementInform(uint32 type, uint32 pointId) override
@@ -421,7 +421,7 @@ class boss_lady_deathwhisper : public CreatureScript
void UpdateAI(uint32 diff) override
{
if ((!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) || !CheckInRoom())
if ((!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)))
return;
events.Update(diff);
@@ -1043,8 +1043,9 @@ class at_lady_deathwhisper_entrance : public AreaTriggerScript
bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
if (InstanceScript* instance = player->GetInstanceScript())
if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER)))
ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO);
if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE)
if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER)))
ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO);
return true;
}
@@ -186,7 +186,7 @@ class boss_lord_marrowgar : public CreatureScript
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -564,7 +564,7 @@ class boss_professor_putricide : public CreatureScript
void UpdateAI(uint32 diff) override
{
if ((!(events.IsInPhase(PHASE_ROTFACE) || events.IsInPhase(PHASE_FESTERGUT)) && !UpdateVictim()) || !CheckInRoom())
if ((!(events.IsInPhase(PHASE_ROTFACE) || events.IsInPhase(PHASE_FESTERGUT)) && !UpdateVictim()))
return;
events.Update(diff);
@@ -119,7 +119,7 @@ class boss_rotface : public CreatureScript
{
if (!instance->CheckRequiredBosses(DATA_ROTFACE, who->ToPlayer()))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
return;
}
@@ -155,9 +155,9 @@ class boss_rotface : public CreatureScript
Talk(SAY_KILL);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
if (Creature* professor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PROFESSOR_PUTRICIDE)))
professor->AI()->EnterEvadeMode();
}
@@ -179,7 +179,7 @@ class boss_rotface : public CreatureScript
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -417,7 +417,7 @@ class boss_sindragosa : public CreatureScript
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -538,7 +538,7 @@ class boss_the_lich_king : public CreatureScript
{
if (!instance->CheckRequiredBosses(DATA_THE_LICH_KING, target->ToPlayer()))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
return;
}
@@ -581,10 +581,10 @@ class boss_the_lich_king : public CreatureScript
return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->SetBossState(DATA_THE_LICH_KING, FAIL);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING)))
tirion->AI()->EnterEvadeMode();
DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS);
@@ -1724,7 +1724,7 @@ class npc_terenas_menethil : public CreatureScript
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
// no running back home
if (!me->IsAlive())
@@ -1967,7 +1967,7 @@ class npc_broken_frostmourne : public CreatureScript
_events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6000, 0, PHASE_OUTRO);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
}
@@ -557,6 +557,8 @@ class npc_green_dragon_combat_trigger : public CreatureScript
if (!me->IsInCombat())
return;
// @TODO check out of bounds on all encounter creatures, evade if matched
std::list<HostileReference*> const& threatList = me->getThreatManager().getThreatList();
if (threatList.empty())
{
@@ -1283,16 +1283,16 @@ struct npc_argent_captainAI : public ScriptedAI
return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
// not yet following
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != CHASE_MOTION_TYPE || IsUndead)
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
return;
}
if (!_EnterEvadeMode())
if (!_EnterEvadeMode(why))
return;
if (!me->GetVehicle())
@@ -47,34 +47,54 @@ enum TimedEvents
EVENT_RESPAWN_GUNSHIP = 4
};
BossBoundaryData const boundaries =
{
{ DATA_LORD_MARROWGAR, new CircleBoundary(Position(-428.0f,2211.0f), 95.0) },
{ DATA_LORD_MARROWGAR, new RectangleBoundary(-430.0f, -330.0f, 2110.0f, 2310.0f) },
{ DATA_LADY_DEATHWHISPER, new RectangleBoundary(-670.0f, -520.0f, 2145.0f, 2280.0f) },
{ DATA_DEATHBRINGER_SAURFANG, new RectangleBoundary(-565.0f, -465.0f, 2160.0f, 2260.0f) },
{ DATA_ROTFACE, new RectangleBoundary(4385.0f, 4505.0f, 3082.0f, 3195.0f) },
{ DATA_FESTERGUT, new RectangleBoundary(4205.0f, 4325.0f, 3082.0f, 3195.0f) },
{ DATA_PROFESSOR_PUTRICIDE, new ParallelogramBoundary(Position(4356.0f, 3290.0f), Position(4435.0f, 3194.0f), Position(4280.0f, 3194.0f)) },
{ DATA_PROFESSOR_PUTRICIDE, new RectangleBoundary(4280.0f, 4435.0f, 3150.0f, 4360.0f) },
{ DATA_BLOOD_PRINCE_COUNCIL, new EllipseBoundary(Position(4660.95f, 2769.194f), 85.0, 60.0) },
{ DATA_BLOOD_QUEEN_LANA_THEL, new CircleBoundary(Position(4595.93f, 2769.365f), 64.0) },
{ DATA_SISTER_SVALNA, new RectangleBoundary(4291.0f, 4423.0f, 2438.0f, 2653.0f) },
{ DATA_VALITHRIA_DREAMWALKER, new RectangleBoundary(4112.5f, 4293.5f, 2385.0f, 2585.0f) },
{ DATA_SINDRAGOSA, new EllipseBoundary(Position(4408.6f, 2484.0f), 100.0, 75.0) }
};
DoorData const doorData[] =
{
{GO_LORD_MARROWGAR_S_ENTRANCE, DATA_LORD_MARROWGAR, DOOR_TYPE_ROOM, BOUNDARY_N },
{GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM, BOUNDARY_N },
{GO_SAURFANG_S_DOOR, DATA_DEATHBRINGER_SAURFANG, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM, BOUNDARY_E },
{GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM, BOUNDARY_E },
{GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM, BOUNDARY_E },
{GO_CRIMSON_HALL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_BLOOD_ELF_COUNCIL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_W },
{GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_DOODAD_ICECROWN_GRATE_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_SISTER_SVALNA, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM, BOUNDARY_N },
{GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_01, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_N },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_02, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_S },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_03, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_N },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_04, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_S },
{GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SE },
{GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SW },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
{GO_LORD_MARROWGAR_S_ENTRANCE, DATA_LORD_MARROWGAR, DOOR_TYPE_ROOM },
{GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE },
{GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE },
{GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM },
{GO_SAURFANG_S_DOOR, DATA_DEATHBRINGER_SAURFANG, DOOR_TYPE_PASSAGE },
{GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM },
{GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM },
{GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM },
{GO_CRIMSON_HALL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_ROOM },
{GO_BLOOD_ELF_COUNCIL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE },
{GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE },
{GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_ROOM },
{GO_DOODAD_ICECROWN_GRATE_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_PASSAGE },
{GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_SISTER_SVALNA, DOOR_TYPE_PASSAGE },
{GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM },
{GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_01, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_02, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_03, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE },
{GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_04, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_SPAWN_HOLE },
{GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM },
{GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE },
{GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE },
{GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM },
{GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM },
{0, 0, DOOR_TYPE_ROOM } // END
};
// this doesnt have to only store questgivers, also can be used for related quest spawns
@@ -115,6 +135,7 @@ class instance_icecrown_citadel : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
TeamInInstance = 0;
HeroicAttempts = MaxHeroicAttempts;
@@ -173,7 +173,7 @@ public:
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -100,7 +100,7 @@ public:
void UpdateAI(uint32 diff) override
{
if (!UpdateVictimWithGaze() || !CheckInRoom())
if (!UpdateVictimWithGaze())
return;
events.Update(diff);
@@ -391,7 +391,7 @@ class boss_gothik : public CreatureScript
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -537,11 +537,11 @@ class npc_gothik_minion : public CreatureScript
CombatAI::JustDied(owner);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (!gateClose)
{
CombatAI::EnterEvadeMode();
CombatAI::EnterEvadeMode(why);
return;
}
@@ -566,7 +566,7 @@ class npc_gothik_minion : public CreatureScript
{
if (gateClose && (!isOnSameSide(me) || (me->GetVictim() && !isOnSameSide(me->GetVictim()))))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
@@ -115,7 +115,7 @@ public:
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -116,7 +116,7 @@ public:
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
if (HealthBelowPct(30) && !me->HasAura(SPELL_FRENZY_HELPER))
@@ -88,7 +88,7 @@ public:
events.SetPhase(PHASE_NONE);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
Reset(); // teleport back first
_EnterEvadeMode();
@@ -205,7 +205,7 @@ public:
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
if (!UpdateVictim())
return;
events.Update(diff);
@@ -231,7 +231,7 @@ class boss_sapphiron : public CreatureScript
events.Update(diff);
if ((_phase != PHASE_BIRTH && !UpdateVictim()) || !CheckInRoom())
if (_phase != PHASE_BIRTH && !UpdateVictim())
return;
if (_phase == PHASE_GROUND)
@@ -456,6 +456,7 @@ public:
{
Initialize();
instance = creature->GetInstanceScript();
SetBoundary(instance->GetBossBoundary(BOSS_THADDIUS));
}
void Initialize()
@@ -723,6 +724,7 @@ public:
{
Initialize();
instance = creature->GetInstanceScript();
SetBoundary(instance->GetBossBoundary(BOSS_THADDIUS));
}
void Initialize()
@@ -990,7 +992,7 @@ public:
{
npc_teslaAI(Creature* creature) : ScriptedAI(creature) { }
void EnterEvadeMode() override { } // never stop casting due to evade
void EnterEvadeMode(EvadeReason /*why*/) override { } // never stop casting due to evade
void UpdateAI(uint32 /*diff*/) override { } // never do anything unless told
void EnterCombat(Unit* /*who*/) override { }
void DamageTaken(Unit* /*who*/, uint32& damage) override { damage = 0; } // no, you can't kill it
@@ -20,42 +20,75 @@
#include "InstanceScript.h"
#include "naxxramas.h"
BossBoundaryData const boundaries =
{
/* Arachnid Quarter */
{ BOSS_ANUBREKHAN, new CircleBoundary(Position(3273.376709f, -3475.876709f), Position(3195.668213f, -3475.930176f)) },
{ BOSS_FAERLINA, new RectangleBoundary(3315.0f, 3402.0f, -3727.0f, -3590.0f) },
{ BOSS_FAERLINA, new CircleBoundary(Position(3372.68f, -3648.2f), Position(3316.0f, -3704.26f)) },
{ BOSS_MAEXXNA, new CircleBoundary(Position(3502.2587f, -3892.1697f), Position(3418.7422f, -3840.271f)) },
/* Plague Quarter */
{ BOSS_NOTH, new RectangleBoundary(2618.0f, 2754.0f, -3557.43f, -3450.0f) },
{ BOSS_HEIGAN, new CircleBoundary(Position(2772.57f, -3685.28f), 56.0f) },
{ BOSS_LOATHEB, new CircleBoundary(Position(2909.0f, -3997.41f), 57.0f) },
/* Military Quarter */
{ BOSS_RAZUVIOUS, new ZRangeBoundary(260.0f, 287.0f) }, // will not chase onto the upper floor
{ BOSS_GOTHIK, new RectangleBoundary(2627.0f, 2764.0f, -3440.0f, -3275.0f) },
{ BOSS_HORSEMEN, new ParallelogramBoundary(AreaBoundary::DoublePosition(2646.0, -2959.0), AreaBoundary::DoublePosition(2529.0, -3075.0), AreaBoundary::DoublePosition(2506.0, -2854.0)) },
/* Construct Quarter */
{ BOSS_PATCHWERK, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) },
{ BOSS_PATCHWERK, new CircleBoundary(Position(3130.8576f, -3210.36f), Position(3085.37f, -3219.85f), true) }, // entrance slime circle blocker
{ BOSS_GROBBULUS, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) },
{ BOSS_GROBBULUS, new RectangleBoundary(3295.0f, 3340.0f, -3254.2f, -3230.18f, true) }, // entrance door blocker
{ BOSS_GLUTH, new CircleBoundary(Position(3293.0f, -3142.0f), 80.0) },
{ BOSS_GLUTH, new ParallelogramBoundary(AreaBoundary::DoublePosition(3401.0, -3149.0), AreaBoundary::DoublePosition(3261.0, -3028.0), AreaBoundary::DoublePosition(3320.0, -3267.0)) },
{ BOSS_GLUTH, new ZRangeBoundary(285.0f, 310.0f) },
{ BOSS_THADDIUS, new ParallelogramBoundary(AreaBoundary::DoublePosition(3478.3, -3070.0), AreaBoundary::DoublePosition(3370.0, -2961.5), AreaBoundary::DoublePosition(3580.0, -2961.5)) },
/* Frostwyrm Lair */
{ BOSS_SAPPHIRON, new CircleBoundary(Position(3517.627f, -5255.5f), 110.0) },
{ BOSS_KELTHUZAD, new CircleBoundary(Position(3716.0f, -5107.0f), 85.0) }
};
DoorData const doorData[] =
{
{ GO_ROOM_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
{ GO_PASSAGE_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_PASSAGE_FAERLINA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_MAEXXNA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_MAEXXNA, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW },
{ GO_ROOM_NOTH, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N },
{ GO_PASSAGE_NOTH, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{ GO_ROOM_HEIGAN, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N },
{ GO_PASSAGE_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{ GO_ROOM_LOATHEB, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_LOATHEB, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W },
{ GO_ROOM_GROBBULUS, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_GROBBULUS, BOSS_GROBBULUS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_PASSAGE_GLUTH, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW },
{ GO_ROOM_THADDIUS, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_THADDIUS, BOSS_THADDIUS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ROOM_GOTHIK, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ROOM_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N },
{ GO_PASSAGE_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{ GO_ROOM_HORSEMEN, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GOTHIK_GATE, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ROOM_HORSEMEN, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE },
{ GO_PASSAGE_SAPPHIRON, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W },
{ GO_ROOM_KELTHUZAD, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S },
{ GO_ARAC_EYE_RAMP, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ARAC_EYE_RAMP_BOSS, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_PLAG_EYE_RAMP, BOSS_LOATHEB, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_PLAG_EYE_RAMP_BOSS, BOSS_LOATHEB, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_MILI_EYE_RAMP, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_MILI_EYE_RAMP_BOSS, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_CONS_EYE_RAMP, BOSS_THADDIUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_CONS_EYE_RAMP_BOSS, BOSS_THADDIUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
{ GO_ROOM_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_ROOM },
{ GO_PASSAGE_ANUBREKHAN, BOSS_ANUBREKHAN, DOOR_TYPE_PASSAGE },
{ GO_PASSAGE_FAERLINA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE },
{ GO_ROOM_MAEXXNA, BOSS_FAERLINA, DOOR_TYPE_PASSAGE },
{ GO_ROOM_MAEXXNA, BOSS_MAEXXNA, DOOR_TYPE_ROOM },
{ GO_ROOM_NOTH, BOSS_NOTH, DOOR_TYPE_ROOM },
{ GO_PASSAGE_NOTH, BOSS_NOTH, DOOR_TYPE_PASSAGE },
{ GO_ROOM_HEIGAN, BOSS_NOTH, DOOR_TYPE_PASSAGE },
{ GO_ROOM_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_ROOM },
{ GO_PASSAGE_HEIGAN, BOSS_HEIGAN, DOOR_TYPE_PASSAGE },
{ GO_ROOM_LOATHEB, BOSS_HEIGAN, DOOR_TYPE_PASSAGE },
{ GO_ROOM_LOATHEB, BOSS_LOATHEB, DOOR_TYPE_ROOM },
{ GO_ROOM_GROBBULUS, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE },
{ GO_ROOM_GROBBULUS, BOSS_GROBBULUS, DOOR_TYPE_ROOM },
{ GO_PASSAGE_GLUTH, BOSS_GLUTH, DOOR_TYPE_PASSAGE },
{ GO_ROOM_THADDIUS, BOSS_GLUTH, DOOR_TYPE_PASSAGE },
{ GO_ROOM_THADDIUS, BOSS_THADDIUS, DOOR_TYPE_ROOM },
{ GO_ROOM_GOTHIK, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE },
{ GO_ROOM_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_ROOM },
{ GO_PASSAGE_GOTHIK, BOSS_GOTHIK, DOOR_TYPE_PASSAGE },
{ GO_ROOM_HORSEMEN, BOSS_GOTHIK, DOOR_TYPE_PASSAGE },
{ GO_GOTHIK_GATE, BOSS_GOTHIK, DOOR_TYPE_ROOM },
{ GO_ROOM_HORSEMEN, BOSS_HORSEMEN, DOOR_TYPE_ROOM },
{ GO_PASSAGE_SAPPHIRON, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE },
{ GO_ROOM_KELTHUZAD, BOSS_KELTHUZAD, DOOR_TYPE_ROOM },
{ GO_ARAC_EYE_RAMP, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE },
{ GO_ARAC_EYE_RAMP_BOSS, BOSS_MAEXXNA, DOOR_TYPE_PASSAGE },
{ GO_PLAG_EYE_RAMP, BOSS_LOATHEB, DOOR_TYPE_PASSAGE },
{ GO_PLAG_EYE_RAMP_BOSS, BOSS_LOATHEB, DOOR_TYPE_PASSAGE },
{ GO_MILI_EYE_RAMP, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE },
{ GO_MILI_EYE_RAMP_BOSS, BOSS_HORSEMEN, DOOR_TYPE_PASSAGE },
{ GO_CONS_EYE_RAMP, BOSS_THADDIUS, DOOR_TYPE_PASSAGE },
{ GO_CONS_EYE_RAMP_BOSS, BOSS_THADDIUS, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM }
};
MinionData const minionData[] =
@@ -117,6 +150,7 @@ class instance_naxxramas : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
LoadMinionData(minionData);
LoadObjectData(nullptr, objectData);
@@ -574,7 +574,7 @@ public:
me->setActive(true);
if (!instance->CheckRequiredBosses(DATA_MALYGOS_EVENT))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
@@ -585,7 +585,7 @@ public:
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
instance->SetBossState(DATA_MALYGOS_EVENT, FAIL);
@@ -1282,7 +1282,7 @@ public:
VehicleAI::Reset();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
}
@@ -1341,7 +1341,7 @@ class npc_nexus_lord : public CreatureScript
_events.Reset();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
}
@@ -1430,7 +1430,7 @@ class npc_scion_of_eternity : public CreatureScript
{
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
}
@@ -21,6 +21,11 @@
#include "eye_of_eternity.h"
#include "Player.h"
BossBoundaryData const boundaries =
{
{ DATA_MALYGOS_EVENT, new CircleBoundary(Position(754.362f, 1301.609985f), 280.0) } // sanity check boundary
};
class instance_eye_of_eternity : public InstanceMapScript
{
public:
@@ -37,6 +42,7 @@ public:
{
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTER);
LoadBossBoundaries(boundaries);
}
void OnPlayerEnter(Player* player) override
@@ -23,8 +23,8 @@
DoorData const doorData[] =
{
{ GO_DRAGON_CAGE_DOOR, DATA_DRAKOS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
{ GO_DRAGON_CAGE_DOOR, DATA_DRAKOS, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM }
};
Position const VerdisaMove = { 949.188f, 1032.91f, 359.967f, 1.093027f };
@@ -187,14 +187,14 @@ public:
instance->SetBossState(DATA_BJARNGRIM, NOT_STARTED);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE))
canBuff = true;
else
canBuff = false;
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void EnterCombat(Unit* /*who*/) override
Loaded 100 of 134 files, more files were not shown because too many files have changed in this diff. Show more