Chantier Rivage brise : materiel de reference et outillage d extraction
Rien n est applique au serveur. Ce commit ne fait que persister le travail de reperage, qui vivait dans /home/ubuntu/tmp et aurait ete perdu. LE BLOCAGE. instance_template reclame pour la carte 1666 un script nomme scenario_7.2_broken_shore_intro qui n existe nulle part dans notre code -- script fantome. La table scenarios n a aucune ligne pour cette carte. Les quetes 45102 et 46734 sont donc infranchissables. RASSEMBLE depuis dufernst/LegionCore-7.3.5 (meme lignee uwow) : - AssaultBrokenShore.cpp (500 lignes) et instance_AssaultBrokenShore.cpp (308 lignes) ; - reperage de 593 placements de creatures (67 entrees) et 59 placements d objets (52 entrees) sur la carte 1666, dans le dump world du depot. NOTRE BASE possede deja les 67 modeles de creatures et les 52 modeles d objets -- aucun manquant. Elle possede aussi les repliques francaises de Vol jin (90708) et Sylvanas (90709), qui n ont ni spawn ni script. DECISIONS DE TRANSPOSITION etablies sur donnees, pas supposees : - spawnMask 4096 = 2^12 -> spawnDifficulties '12', la difficulte 12 etant « Normal Scenario » d apres Difficulty.db2 du build 7.3.5.26972 ; - GUID renumerotes au-dessus de nos maxima (290000114 / 210120986) ; - huit colonnes de la reference sans equivalent chez nous, abandonnees. DEPENDANCES DECOUVERTES : 180 des 593 creatures ont MovementType 2 et suivent donc des chemins a extraire aussi ; 12 portent un AiID renvoyant a une table propre au coeur de reference, comportement a refaire. PIEGE CONSIGNE dans le README : le premier extracteur renvoyait zero ligne, ce qui aurait fait conclure a tort que la reference etait vide. Les instructions insert du dump s etalent sur plusieurs lignes. C est un controle sur cas positif connu qui a revele le bug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
# Chantier — Assaut du Rivage brisé (carte 1666)
|
||||||
|
|
||||||
|
État au 27/08/2026. **Rien n'est appliqué au serveur à ce stade.**
|
||||||
|
|
||||||
|
## Le blocage d'origine
|
||||||
|
|
||||||
|
`instance_template` réclame pour la carte 1666 un script nommé
|
||||||
|
`scenario_7.2_broken_shore_intro` qui **n'existe nulle part dans notre code** —
|
||||||
|
script fantôme. La table `scenarios` n'a par ailleurs aucune ligne pour cette
|
||||||
|
carte. Conséquence : les quêtes `45102 Begin the Assault` et
|
||||||
|
`46734 Assault on Broken Shore` sont infranchissables.
|
||||||
|
|
||||||
|
## Ce qui a été rassemblé
|
||||||
|
|
||||||
|
Source : `dufernst/LegionCore-7.3.5` (même lignée uwow que notre fork).
|
||||||
|
|
||||||
|
| Élément | Volume | Emplacement |
|
||||||
|
|---|---|---|
|
||||||
|
| Script du scénario | 500 lignes | `reference/AssaultBrokenShore.cpp` |
|
||||||
|
| Script d'instance | 308 lignes | `reference/instance_AssaultBrokenShore.cpp` |
|
||||||
|
| Placements de créatures | **593 spawns**, 67 entrées | à extraire du dump |
|
||||||
|
| Placements d'objets | **59 spawns**, 52 entrées | à extraire du dump |
|
||||||
|
|
||||||
|
Le dump complet (`LegionCore_world_2020_04_25.zip`, 39 Mo compressés / 232 Mo)
|
||||||
|
n'est **pas** versionné : il se retélécharge depuis le dépôt de référence,
|
||||||
|
chemin `sql/base/`.
|
||||||
|
|
||||||
|
## Ce que notre base possède déjà
|
||||||
|
|
||||||
|
- Les **67 modèles de créatures** : présents, aucun manquant.
|
||||||
|
- Les **52 modèles d'objets** : présents, aucun manquant.
|
||||||
|
- Les répliques françaises de Vol'jin (90708) et Sylvanas (90709), y compris
|
||||||
|
la blessure empoisonnée qui déclenche la retraite. Ces deux-là n'ont
|
||||||
|
cependant **aucun spawn ni script**.
|
||||||
|
|
||||||
|
## Décisions de transposition, établies sur données
|
||||||
|
|
||||||
|
Les deux schémas divergent. Correspondances retenues :
|
||||||
|
|
||||||
|
| Référence | Nous | Décision |
|
||||||
|
|---|---|---|
|
||||||
|
| `spawnMask = 4096` | `spawnDifficulties` | **`'12'`** — 4096 = 2¹², et la difficulté 12 est « Normal Scenario » (type instance 5) d'après `Difficulty.db2` du build 7.3.5.26972 |
|
||||||
|
| `phaseMask = 1` | `phaseUseFlags`, `PhaseGroup` | valeurs neutres : aucun phasage réel à transposer |
|
||||||
|
| `PhaseId` | `PhaseId` | direct — vaut `''` sauf 3 créatures à `7043` |
|
||||||
|
| `guid` | `guid` | **renumérotés** au-dessus de nos maxima (créature 290000114, objet 210120986) |
|
||||||
|
| — | `terrainSwapMap` | `-1`, valeur employée par nos autres instances |
|
||||||
|
| `npcflag2`, `AiID`, `MovementID`, `MeleeID`, `isActive`, `skipClone`, `personal_size`, `isTeemingSpawn` | — | **abandonnées**, ces colonnes n'existent pas chez nous |
|
||||||
|
|
||||||
|
## Dépendances découvertes, à ne pas oublier
|
||||||
|
|
||||||
|
1. **180 créatures sur 593 ont `MovementType = 2`** : elles suivent des
|
||||||
|
chemins. Sans extraction de `waypoint_data` pour leurs GUID, elles
|
||||||
|
apparaîtront figées.
|
||||||
|
2. **12 créatures portent `AiID = 7424`**, une table d'IA propre au cœur de
|
||||||
|
référence que nous n'avons pas. Ce comportement sera **perdu** et devra
|
||||||
|
être refait autrement — probablement en SmartAI.
|
||||||
|
3. Le dump contient `scenario_data`, `scenario_poi`, `scenario_poi_points` et
|
||||||
|
`scenario_step_spells` : la déclaration du scénario s'y trouve aussi.
|
||||||
|
4. Le script s'enregistre sous `instance_AssaultBrokenShore` alors que notre
|
||||||
|
`instance_template` réclame `scenario_7.2_broken_shore_intro`. À raccorder.
|
||||||
|
|
||||||
|
## Piège rencontré, à retenir
|
||||||
|
|
||||||
|
Le premier extracteur écrit pour ce travail renvoyait **zéro ligne** pour la
|
||||||
|
carte 1666, ce qui aurait fait conclure à tort que la référence ne contenait
|
||||||
|
rien. Cause : dans ce dump, une instruction `insert into` s'étale sur
|
||||||
|
plusieurs lignes, et l'analyse ligne à ligne ne voyait que la première.
|
||||||
|
|
||||||
|
C'est un contrôle de cohérence — vérifier que le parseur trouvait bien des
|
||||||
|
lignes sur des cartes connues — qui a révélé le bug. **Toujours valider un
|
||||||
|
extracteur sur un cas positif connu avant de croire un résultat négatif.**
|
||||||
|
|
||||||
|
## Reste à faire
|
||||||
|
|
||||||
|
1. Extraire et transposer les 593 + 59 placements.
|
||||||
|
2. Extraire les chemins des 180 créatures mobiles.
|
||||||
|
3. Transposer la déclaration du scénario.
|
||||||
|
4. Porter les 808 lignes de C++ et les adapter à notre API, qui a divergé
|
||||||
|
(`MoveJump`, `SetFacingTo`, `GetEffect` diffèrent déjà — constaté ailleurs).
|
||||||
|
5. Raccorder le nom de script.
|
||||||
|
6. Refaire autrement le comportement des 12 créatures à `AiID`.
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Extraction carte 1666 — version corrigee : une instruction INSERT
|
||||||
|
s'etale sur plusieurs lignes, on accumule jusqu'au point-virgule final."""
|
||||||
|
import io, re
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
CHEMIN = '/home/ubuntu/tmp/abs/LegionCore_world_2020_04_25.sql'
|
||||||
|
motif = re.compile(r"insert\s+into\s+`(creature|gameobject)`\(([^)]*)\)\s+values\s*", re.I)
|
||||||
|
|
||||||
|
|
||||||
|
def decoupe_tuples(bloc):
|
||||||
|
tuples, courant, prof, chaine, echap = [], [], 0, False, False
|
||||||
|
for c in bloc:
|
||||||
|
if chaine:
|
||||||
|
courant.append(c)
|
||||||
|
if echap:
|
||||||
|
echap = False
|
||||||
|
elif c == '\\':
|
||||||
|
echap = True
|
||||||
|
elif c == "'":
|
||||||
|
chaine = False
|
||||||
|
continue
|
||||||
|
if c == "'":
|
||||||
|
chaine = True
|
||||||
|
courant.append(c)
|
||||||
|
elif c == '(':
|
||||||
|
prof += 1
|
||||||
|
if prof == 1:
|
||||||
|
courant = []
|
||||||
|
else:
|
||||||
|
courant.append(c)
|
||||||
|
elif c == ')':
|
||||||
|
prof -= 1
|
||||||
|
if prof == 0:
|
||||||
|
tuples.append(''.join(courant))
|
||||||
|
else:
|
||||||
|
courant.append(c)
|
||||||
|
elif prof > 0:
|
||||||
|
courant.append(c)
|
||||||
|
return tuples
|
||||||
|
|
||||||
|
|
||||||
|
def champs(t):
|
||||||
|
vals, courant, chaine, echap = [], [], False, False
|
||||||
|
for c in t:
|
||||||
|
if chaine:
|
||||||
|
courant.append(c)
|
||||||
|
if echap:
|
||||||
|
echap = False
|
||||||
|
elif c == '\\':
|
||||||
|
echap = True
|
||||||
|
elif c == "'":
|
||||||
|
chaine = False
|
||||||
|
continue
|
||||||
|
if c == "'":
|
||||||
|
chaine = True
|
||||||
|
courant.append(c)
|
||||||
|
elif c == ',':
|
||||||
|
vals.append(''.join(courant).strip())
|
||||||
|
courant = []
|
||||||
|
else:
|
||||||
|
courant.append(c)
|
||||||
|
vals.append(''.join(courant).strip())
|
||||||
|
return vals
|
||||||
|
|
||||||
|
|
||||||
|
stats = {}
|
||||||
|
|
||||||
|
with io.open(CHEMIN, encoding='utf-8', errors='replace') as f:
|
||||||
|
ligne = f.readline()
|
||||||
|
while ligne:
|
||||||
|
m = motif.match(ligne.lstrip())
|
||||||
|
if not m:
|
||||||
|
ligne = f.readline()
|
||||||
|
continue
|
||||||
|
|
||||||
|
table = m.group(1).lower()
|
||||||
|
cols = [c.strip().strip('`') for c in m.group(2).split(',')]
|
||||||
|
|
||||||
|
# accumuler jusqu'au ';' final
|
||||||
|
morceaux = [ligne[ligne.lower().find('values') + 6:]]
|
||||||
|
while not morceaux[-1].rstrip().endswith(';'):
|
||||||
|
suite = f.readline()
|
||||||
|
if not suite:
|
||||||
|
break
|
||||||
|
morceaux.append(suite)
|
||||||
|
bloc = ''.join(morceaux)
|
||||||
|
|
||||||
|
i_map = cols.index('map')
|
||||||
|
i_id = cols.index('id')
|
||||||
|
|
||||||
|
s = stats.setdefault(table, {'cols': cols, 'total': 0, 'cartes': Counter(), 'l1666': []})
|
||||||
|
for t in decoupe_tuples(bloc):
|
||||||
|
v = champs(t)
|
||||||
|
if len(v) != len(cols):
|
||||||
|
continue
|
||||||
|
s['total'] += 1
|
||||||
|
s['cartes'][v[i_map]] += 1
|
||||||
|
if v[i_map] == '1666':
|
||||||
|
s['l1666'].append(v)
|
||||||
|
|
||||||
|
ligne = f.readline()
|
||||||
|
|
||||||
|
for table, s in stats.items():
|
||||||
|
print('=== %s ===' % table)
|
||||||
|
print(' tuples analyses : %d' % s['total'])
|
||||||
|
print(' cartes les plus peuplees : %s' % ', '.join('%s(%d)' % c for c in s['cartes'].most_common(6)))
|
||||||
|
print(' >>> CARTE 1666 : %d lignes' % len(s['l1666']))
|
||||||
|
if s['l1666']:
|
||||||
|
i_id = s['cols'].index('id')
|
||||||
|
c = Counter(l[i_id] for l in s['l1666'])
|
||||||
|
print(' %d entrees distinctes ; top 15 :' % len(c))
|
||||||
|
for e, n in c.most_common():
|
||||||
|
print(' entree %-8s x%d' % (e, n))
|
||||||
|
print()
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Transpose les placements de la carte 1666 du dump de reference vers
|
||||||
|
NOTRE schema. Ne touche a rien : produit un rapport et un fichier SQL.
|
||||||
|
|
||||||
|
Les deux schemas divergent, la correspondance est donc explicite :
|
||||||
|
|
||||||
|
reference nous
|
||||||
|
--------- ----
|
||||||
|
guid guid (RENUMEROTE, voir plus bas)
|
||||||
|
id, map, zoneId, areaId identiques
|
||||||
|
spawnMask spawnDifficulties (a decider, voir rapport)
|
||||||
|
phaseMask -- non transposable, on laisse les valeurs neutres
|
||||||
|
PhaseId PhaseId
|
||||||
|
modelid .. dynamicflags identiques
|
||||||
|
unit_flags3 unit_flags3
|
||||||
|
npcflag2, AiID, -- ABANDONNES : ces colonnes n'existent pas chez
|
||||||
|
MovementID, MeleeID, nous. AiID et MovementID renvoient a des tables
|
||||||
|
isActive, skipClone, propres a ce coeur ; les abandonner fait perdre
|
||||||
|
personal_size, une part du comportement, a recreer autrement.
|
||||||
|
isTeemingSpawn
|
||||||
|
|
||||||
|
Les GUID sont renumerotes au-dessus de nos maxima (creature 290000114,
|
||||||
|
gameobject 210120986) pour ne heurter aucun spawn existant.
|
||||||
|
"""
|
||||||
|
import io, re, sys
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
CHEMIN = '/home/ubuntu/tmp/abs/LegionCore_world_2020_04_25.sql'
|
||||||
|
SORTIE = '/home/ubuntu/tmp/abs/rivage_brise_spawns.sql'
|
||||||
|
|
||||||
|
GUID_CREATURE_DEPART = 290100000
|
||||||
|
GUID_GO_DEPART = 210200000
|
||||||
|
|
||||||
|
# colonnes de NOTRE schema
|
||||||
|
NOS_CREATURE = ['guid','id','map','zoneId','areaId','spawnDifficulties','phaseUseFlags','PhaseId',
|
||||||
|
'PhaseGroup','terrainSwapMap','modelid','equipment_id','position_x','position_y',
|
||||||
|
'position_z','orientation','spawntimesecs','spawndist','currentwaypoint','curhealth',
|
||||||
|
'curmana','MovementType','npcflag','unit_flags','unit_flags2','unit_flags3',
|
||||||
|
'dynamicflags','ScriptName','movementmode','VerifiedBuild']
|
||||||
|
|
||||||
|
NOS_GO = ['guid','id','map','zoneId','areaId','spawnDifficulties','phaseUseFlags','PhaseId',
|
||||||
|
'PhaseGroup','terrainSwapMap','position_x','position_y','position_z','orientation',
|
||||||
|
'rotation0','rotation1','rotation2','rotation3','spawntimesecs','animprogress','state',
|
||||||
|
'isActive','ScriptName','VerifiedBuild']
|
||||||
|
|
||||||
|
|
||||||
|
def decoupe_tuples(bloc):
|
||||||
|
res, cur, prof, chaine, echap = [], [], 0, False, False
|
||||||
|
for c in bloc:
|
||||||
|
if chaine:
|
||||||
|
cur.append(c)
|
||||||
|
if echap: echap = False
|
||||||
|
elif c == '\\': echap = True
|
||||||
|
elif c == "'": chaine = False
|
||||||
|
continue
|
||||||
|
if c == "'":
|
||||||
|
chaine = True; cur.append(c)
|
||||||
|
elif c == '(':
|
||||||
|
prof += 1
|
||||||
|
if prof == 1: cur = []
|
||||||
|
else: cur.append(c)
|
||||||
|
elif c == ')':
|
||||||
|
prof -= 1
|
||||||
|
if prof == 0: res.append(''.join(cur))
|
||||||
|
else: cur.append(c)
|
||||||
|
elif prof > 0:
|
||||||
|
cur.append(c)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def champs(t):
|
||||||
|
vals, cur, chaine, echap = [], [], False, False
|
||||||
|
for c in t:
|
||||||
|
if chaine:
|
||||||
|
cur.append(c)
|
||||||
|
if echap: echap = False
|
||||||
|
elif c == '\\': echap = True
|
||||||
|
elif c == "'": chaine = False
|
||||||
|
continue
|
||||||
|
if c == "'":
|
||||||
|
chaine = True; cur.append(c)
|
||||||
|
elif c == ',':
|
||||||
|
vals.append(''.join(cur).strip()); cur = []
|
||||||
|
else:
|
||||||
|
cur.append(c)
|
||||||
|
vals.append(''.join(cur).strip())
|
||||||
|
return vals
|
||||||
|
|
||||||
|
|
||||||
|
motif = re.compile(r"insert\s+into\s+`(creature|gameobject)`\(([^)]*)\)\s+values\s*", re.I)
|
||||||
|
recolte = {'creature': {'cols': None, 'lignes': []}, 'gameobject': {'cols': None, 'lignes': []}}
|
||||||
|
|
||||||
|
with io.open(CHEMIN, encoding='utf-8', errors='replace') as f:
|
||||||
|
ligne = f.readline()
|
||||||
|
while ligne:
|
||||||
|
m = motif.match(ligne.lstrip())
|
||||||
|
if not m:
|
||||||
|
ligne = f.readline(); continue
|
||||||
|
table = m.group(1).lower()
|
||||||
|
cols = [c.strip().strip('`') for c in m.group(2).split(',')]
|
||||||
|
morceaux = [ligne[ligne.lower().find('values') + 6:]]
|
||||||
|
while not morceaux[-1].rstrip().endswith(';'):
|
||||||
|
s = f.readline()
|
||||||
|
if not s: break
|
||||||
|
morceaux.append(s)
|
||||||
|
i_map = cols.index('map')
|
||||||
|
recolte[table]['cols'] = cols
|
||||||
|
for t in decoupe_tuples(''.join(morceaux)):
|
||||||
|
v = champs(t)
|
||||||
|
if len(v) == len(cols) and v[i_map] == '1666':
|
||||||
|
recolte[table]['lignes'].append(v)
|
||||||
|
ligne = f.readline()
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# RAPPORT : ce que je ne peux pas transposer mecaniquement
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
print('================= RAPPORT DE TRANSPOSITION =================')
|
||||||
|
for table in ('creature', 'gameobject'):
|
||||||
|
r = recolte[table]
|
||||||
|
print('\n--- %s : %d lignes ---' % (table, len(r['lignes'])))
|
||||||
|
if not r['lignes']:
|
||||||
|
continue
|
||||||
|
cols = r['cols']
|
||||||
|
for nom in ('spawnMask', 'phaseMask', 'PhaseId', 'spawntimesecs', 'MovementType', 'AiID', 'MovementID', 'isActive'):
|
||||||
|
if nom in cols:
|
||||||
|
i = cols.index(nom)
|
||||||
|
c = Counter(l[i] for l in r['lignes'])
|
||||||
|
print(' %-14s : %s' % (nom, ', '.join('%s(x%d)' % x for x in c.most_common(6))))
|
||||||
|
|
||||||
|
print('\n(la generation SQL n est PAS lancee : on decide d abord de spawnDifficulties)')
|
||||||
@@ -0,0 +1,501 @@
|
|||||||
|
/*
|
||||||
|
BrokenShore
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ScriptMgr.h"
|
||||||
|
#include "ScriptedCreature.h"
|
||||||
|
#include "CreatureTextMgr.h"
|
||||||
|
#include "GameObjectAI.h"
|
||||||
|
#include "QuestData.h"
|
||||||
|
#include "ObjectVisitors.hpp"
|
||||||
|
|
||||||
|
// + Smart: 122105 120515 118444 119130
|
||||||
|
// 119133, 118412, 121232, 118966, 121146, 118969, 118945
|
||||||
|
class npc_broken_shore_misc : public CreatureScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
npc_broken_shore_misc() : CreatureScript("npc_broken_shore_misc") { }
|
||||||
|
|
||||||
|
CreatureAI* GetAI(Creature* creature) const override
|
||||||
|
{
|
||||||
|
return new npc_broken_shore_miscAI(creature);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct npc_broken_shore_miscAI : ScriptedAI
|
||||||
|
{
|
||||||
|
npc_broken_shore_miscAI(Creature* creature) : ScriptedAI(creature)
|
||||||
|
{
|
||||||
|
instance = me->GetInstanceScript();
|
||||||
|
justSawByPlayer = false; // if player didn't saw this npc, then npc is 'freezing'
|
||||||
|
}
|
||||||
|
|
||||||
|
EventMap events;
|
||||||
|
InstanceScript* instance;
|
||||||
|
FunctionProcessor _functions;
|
||||||
|
bool justSawByPlayer;
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
|
{
|
||||||
|
events.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterCombat(Unit* who) override
|
||||||
|
{
|
||||||
|
switch(me->GetEntry())
|
||||||
|
{
|
||||||
|
case 119133:
|
||||||
|
events.RescheduleEvent(EVENT_1, 6000); // 226063
|
||||||
|
DoCast(225184);
|
||||||
|
break;
|
||||||
|
case 118412:
|
||||||
|
events.RescheduleEvent(EVENT_2, 2500); // 183108
|
||||||
|
events.RescheduleEvent(EVENT_3, 18000); // 183075
|
||||||
|
break;
|
||||||
|
case 121232:
|
||||||
|
events.RescheduleEvent(EVENT_4, 2300); // 182856
|
||||||
|
events.RescheduleEvent(EVENT_5, 14000); // 182854 (friendly)
|
||||||
|
DoCast(79833);
|
||||||
|
break;
|
||||||
|
case 118966:
|
||||||
|
events.RescheduleEvent(EVENT_6, 4000); // 190330
|
||||||
|
events.RescheduleEvent(EVENT_7, 35000); // 189804
|
||||||
|
events.RescheduleEvent(EVENT_8, 11000); // 190332
|
||||||
|
events.RescheduleEvent(EVENT_9, 14000); // 190331
|
||||||
|
break;
|
||||||
|
case 121146:
|
||||||
|
events.RescheduleEvent(EVENT_10, 3000); // 183555
|
||||||
|
events.RescheduleEvent(EVENT_11, 13000); // 183553
|
||||||
|
events.RescheduleEvent(EVENT_12, 15000); // 183549 (friendly)
|
||||||
|
break;
|
||||||
|
case 118969:
|
||||||
|
events.RescheduleEvent(EVENT_13, 7000); // 222971
|
||||||
|
events.RescheduleEvent(EVENT_14, 27000); // 223061
|
||||||
|
events.RescheduleEvent(EVENT_15, 21000); // 223109
|
||||||
|
events.RescheduleEvent(EVENT_16, 31000); // 223903
|
||||||
|
break;
|
||||||
|
case 118945:
|
||||||
|
events.RescheduleEvent(EVENT_17, 4000); // 183894
|
||||||
|
events.RescheduleEvent(EVENT_18, 9000); // 183897
|
||||||
|
events.RescheduleEvent(EVENT_19, 39000); // 183898
|
||||||
|
events.RescheduleEvent(EVENT_20, 31000); // 190010
|
||||||
|
break;
|
||||||
|
case 118444:
|
||||||
|
events.RescheduleEvent(EVENT_21, 3000); // 183108
|
||||||
|
events.RescheduleEvent(EVENT_22, 20000); // 13730
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterEvadeMode() override
|
||||||
|
{
|
||||||
|
if (instance->getScenarionStep() == 1)
|
||||||
|
{
|
||||||
|
if (!DoFindAnyProblem())
|
||||||
|
me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + irand(-10, 10), me->GetPositionY() + 10.0f, me->GetPositionZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType dmgType) override
|
||||||
|
{
|
||||||
|
damage /= (11-(me->GetHealthPct()/10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
|
{
|
||||||
|
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
|
||||||
|
if (type == WAYPOINT_MOTION_TYPE)
|
||||||
|
{
|
||||||
|
if (instance->getScenarionStep() == 3) // kill some npc after maiev
|
||||||
|
DoFindAnyProblem();
|
||||||
|
}
|
||||||
|
else if (type == POINT_MOTION_TYPE)
|
||||||
|
{
|
||||||
|
if (id == 1)
|
||||||
|
{
|
||||||
|
EnterEvadeMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveInLineOfSight(Unit* who) override
|
||||||
|
{
|
||||||
|
if (who->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!justSawByPlayer)
|
||||||
|
{
|
||||||
|
if (me->GetEntry() == 119133)
|
||||||
|
if (me->IsWithinDistInMap(who, 40.0f))
|
||||||
|
instance->onScenarionNextStep(20); // custom
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
justSawByPlayer = true;
|
||||||
|
|
||||||
|
switch(instance->getScenarionStep())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if (!DoFindAnyProblem())
|
||||||
|
me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + irand(-10, 10), me->GetPositionY() + 10.0f, me->GetPositionZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (me->HasUnitState(UNIT_STATE_STUNNED)) // need for this
|
||||||
|
return;
|
||||||
|
|
||||||
|
_functions.Update(diff);
|
||||||
|
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
events.Update(diff);
|
||||||
|
|
||||||
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (uint32 eventId = events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_1:
|
||||||
|
DoCast(226063);
|
||||||
|
events.RescheduleEvent(EVENT_1, 6000); // 226063
|
||||||
|
break;
|
||||||
|
case EVENT_2:
|
||||||
|
DoCast(183108);
|
||||||
|
events.RescheduleEvent(EVENT_2, 2500); // 183108
|
||||||
|
break;
|
||||||
|
case EVENT_3:
|
||||||
|
DoCast(183075);
|
||||||
|
events.RescheduleEvent(EVENT_3, 18000); // 183075
|
||||||
|
break;
|
||||||
|
case EVENT_4:
|
||||||
|
DoCast(182856);
|
||||||
|
events.RescheduleEvent(EVENT_4, 2300); // 182856
|
||||||
|
break;
|
||||||
|
case EVENT_5:
|
||||||
|
if (Unit* target = FindNearestFriendlyUnit())
|
||||||
|
me->CastSpell(target, 182854);
|
||||||
|
events.RescheduleEvent(EVENT_5, 14000); // 182854 (friendly)
|
||||||
|
break;
|
||||||
|
case EVENT_6:
|
||||||
|
DoCast(190330);
|
||||||
|
events.RescheduleEvent(EVENT_6, 4000); // 190330
|
||||||
|
break;
|
||||||
|
case EVENT_7:
|
||||||
|
DoCast(189804);
|
||||||
|
events.RescheduleEvent(EVENT_7, 35000); // 189804
|
||||||
|
break;
|
||||||
|
case EVENT_8:
|
||||||
|
DoCast(190332);
|
||||||
|
events.RescheduleEvent(EVENT_8, 11000); // 190332
|
||||||
|
break;
|
||||||
|
case EVENT_9:
|
||||||
|
DoCast(190331);
|
||||||
|
events.RescheduleEvent(EVENT_9, 14000); // 190331
|
||||||
|
break;
|
||||||
|
case EVENT_10:
|
||||||
|
DoCast(183555);
|
||||||
|
events.RescheduleEvent(EVENT_10, 3000); // 183555
|
||||||
|
break;
|
||||||
|
case EVENT_11:
|
||||||
|
DoCast(183553);
|
||||||
|
events.RescheduleEvent(EVENT_11, 13000); // 183553
|
||||||
|
break;
|
||||||
|
case EVENT_12:
|
||||||
|
if (Unit* target = FindNearestFriendlyUnit())
|
||||||
|
me->CastSpell(target, 183549);
|
||||||
|
events.RescheduleEvent(EVENT_12, 15000); // 183549 (friendly)
|
||||||
|
break;
|
||||||
|
case EVENT_13:
|
||||||
|
DoCast(222971);
|
||||||
|
events.RescheduleEvent(EVENT_13, 7000); // 222971
|
||||||
|
break;
|
||||||
|
case EVENT_14:
|
||||||
|
DoCast(223061);
|
||||||
|
events.RescheduleEvent(EVENT_14, 27000); // 223061
|
||||||
|
break;
|
||||||
|
case EVENT_15:
|
||||||
|
DoCast(223109);
|
||||||
|
events.RescheduleEvent(EVENT_15, 21000); // 223109
|
||||||
|
break;
|
||||||
|
case EVENT_16:
|
||||||
|
DoCast(223903);
|
||||||
|
events.RescheduleEvent(EVENT_16, 31000); // 223903
|
||||||
|
break;
|
||||||
|
case EVENT_17:
|
||||||
|
DoCast(183894);
|
||||||
|
events.RescheduleEvent(EVENT_17, 4000); // 183894
|
||||||
|
break;
|
||||||
|
case EVENT_18:
|
||||||
|
DoCast(183897);
|
||||||
|
events.RescheduleEvent(EVENT_18, 9000); // 183897
|
||||||
|
break;
|
||||||
|
case EVENT_19:
|
||||||
|
DoCast(183898);
|
||||||
|
events.RescheduleEvent(EVENT_19, 39000); // 183898
|
||||||
|
break;
|
||||||
|
case EVENT_20:
|
||||||
|
DoCast(190010);
|
||||||
|
events.RescheduleEvent(EVENT_20, 31000); // 190010
|
||||||
|
break;
|
||||||
|
case EVENT_21:
|
||||||
|
DoCast(183108);
|
||||||
|
events.RescheduleEvent(EVENT_21, 3000); // 183108
|
||||||
|
break;
|
||||||
|
case EVENT_22:
|
||||||
|
DoCast(13730);
|
||||||
|
events.RescheduleEvent(EVENT_22, 20000); // 13730
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom functions
|
||||||
|
|
||||||
|
bool DoFindAnyProblem() // try to find any mobs and start attack this
|
||||||
|
{
|
||||||
|
std::list<Creature*> trash;
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118416, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118456, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118457, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118886, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118453, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118654, 40.0f);
|
||||||
|
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 120511, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118711, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118644, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118647, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118645, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118656, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118655, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118708, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118658, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118563, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118659, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118646, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118650, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118648, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118652, 40.0f);
|
||||||
|
GetCreatureListWithEntryInGrid(trash, me, 118653, 40.0f);
|
||||||
|
for (std::list<Creature*>::iterator itr = trash.begin(); itr != trash.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->isAlive())
|
||||||
|
{
|
||||||
|
AttackStart((*itr));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* FindNearestFriendlyUnit() // for healers
|
||||||
|
{
|
||||||
|
Unit* unit = NULL;
|
||||||
|
Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(me, me, 20);
|
||||||
|
Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, unit, u_check);
|
||||||
|
Trinity::VisitNearbyObject(me, 20, searcher);
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 118517
|
||||||
|
class npc_arcane_raven : public CreatureScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
npc_arcane_raven() : CreatureScript("npc_arcane_raven") {}
|
||||||
|
|
||||||
|
struct npc_arcane_ravenAI : ScriptedAI
|
||||||
|
{
|
||||||
|
npc_arcane_ravenAI(Creature* creature) : ScriptedAI(creature) {}
|
||||||
|
|
||||||
|
void Reset() override {}
|
||||||
|
|
||||||
|
void IsSummonedBy(Unit* summoner) override
|
||||||
|
{
|
||||||
|
SetFlyMode(true);
|
||||||
|
summoner->CastSpell(me, 52391, true); //Ride Veh
|
||||||
|
}
|
||||||
|
|
||||||
|
void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
|
||||||
|
{
|
||||||
|
bool isPlayer = who->IsPlayer();
|
||||||
|
me->AddDelayedEvent(4000, [this, isPlayer]() -> void
|
||||||
|
{
|
||||||
|
if (isPlayer)
|
||||||
|
me->GetMotionMaster()->MovePath(11322708, false);
|
||||||
|
else
|
||||||
|
me->GetMotionMaster()->MovePath(11322708, false, irand(-15, 15), irand(-15, 15));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementInform(uint32 moveType, uint32 pointId) override
|
||||||
|
{
|
||||||
|
if (moveType != WAYPOINT_MOTION_TYPE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pointId == 20 && me->GetAnyOwner())
|
||||||
|
{
|
||||||
|
if (me->GetAnyOwner()->IsPlayer())
|
||||||
|
{
|
||||||
|
me->GetAnyOwner()->CreateConversation(4828);
|
||||||
|
me->GetAnyOwner()->ToPlayer()->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 56460);
|
||||||
|
if (Creature* infernal = me->SummonCreature(118416, me->GetPositionX() + 5, me->GetPositionY() + 5, me->GetPositionZ()))
|
||||||
|
{
|
||||||
|
infernal->CastSpell(infernal, 205266);
|
||||||
|
if (Creature* mag = infernal->FindNearestCreature(118412, 30.0f, true))
|
||||||
|
{
|
||||||
|
mag->CastSpell(mag, 46604);
|
||||||
|
mag->AI()->Talk(0);
|
||||||
|
}
|
||||||
|
infernal->CastSpell(infernal, 239649);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
me->DespawnOrUnsummon(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CreatureAI* GetAI(Creature* creature) const override
|
||||||
|
{
|
||||||
|
return new npc_arcane_ravenAI(creature);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 118558 120743
|
||||||
|
class npc_bs_legion_portal : public CreatureScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
npc_bs_legion_portal() : CreatureScript("npc_bs_legion_portal") { }
|
||||||
|
|
||||||
|
CreatureAI* GetAI(Creature* creature) const override
|
||||||
|
{
|
||||||
|
return new npc_bs_legion_portalAI(creature);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct npc_bs_legion_portalAI : ScriptedAI
|
||||||
|
{
|
||||||
|
npc_bs_legion_portalAI(Creature* creature) : ScriptedAI(creature)
|
||||||
|
{
|
||||||
|
me->SetReactState(REACT_PASSIVE);
|
||||||
|
me->SetFlag(UNIT_FIELD_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveInLineOfSight(Unit* who) override {}
|
||||||
|
|
||||||
|
void OnSpellClick(Unit* clicker) override
|
||||||
|
{
|
||||||
|
if (!clicker->IsPlayer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
me->RemoveFlag(UNIT_FIELD_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||||
|
if (me->GetEntry() == 118558)
|
||||||
|
{
|
||||||
|
clicker->ToPlayer()->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT, 56778);
|
||||||
|
// me->DespawnOrUnsummon(10);
|
||||||
|
}
|
||||||
|
else if (me->GetEntry() == 120743)
|
||||||
|
{
|
||||||
|
clicker->ToPlayer()->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 57574);
|
||||||
|
me->RemoveAura(144373);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 267955
|
||||||
|
class go_bs_demoic_gates : public GameObjectScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
go_bs_demoic_gates() : GameObjectScript("go_bs_demoic_gates") { }
|
||||||
|
|
||||||
|
struct go_bs_demoic_gatesAI : public GameObjectAI
|
||||||
|
{
|
||||||
|
go_bs_demoic_gatesAI(GameObject* go) : GameObjectAI(go){}
|
||||||
|
|
||||||
|
|
||||||
|
bool GossipHello(Player* player) override
|
||||||
|
{
|
||||||
|
if (InstanceScript* instance = go->GetInstanceScript())
|
||||||
|
{
|
||||||
|
if (instance->getScenarionStep() < 5)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Map::PlayerList const &PlList = player->GetMap()->GetPlayers();
|
||||||
|
|
||||||
|
if (PlList.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
|
||||||
|
if (Player* pPlayer = i->getSource())
|
||||||
|
{
|
||||||
|
pPlayer->CastSpell(pPlayer, 236671);
|
||||||
|
pPlayer->UpdateAchievementCriteria(CRITERIA_TYPE_USE_GAMEOBJECT, 267955);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GameObjectAI* GetAI(GameObject* go) const override
|
||||||
|
{
|
||||||
|
return new go_bs_demoic_gatesAI(go);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class player_scripts_for_start_assault : public PlayerScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
player_scripts_for_start_assault() : PlayerScript("player_scripts_for_start_assault")
|
||||||
|
{
|
||||||
|
checktimer = 1000;
|
||||||
|
}
|
||||||
|
uint32 checktimer;
|
||||||
|
|
||||||
|
void OnUpdate(Player* player, uint32 diff) override
|
||||||
|
{
|
||||||
|
if (checktimer <= diff)
|
||||||
|
{
|
||||||
|
if (player)
|
||||||
|
if (player->getLevel() == 110)
|
||||||
|
if (player->GetQuestStatus(46730) == QUEST_STATUS_NONE)
|
||||||
|
{
|
||||||
|
Quest const* quest = sQuestDataStore->GetQuestTemplate(46730);
|
||||||
|
if (quest)
|
||||||
|
if (player->CanTakeQuest(quest, false) && player->CanAddQuest(quest, true))
|
||||||
|
player->AddQuest(quest, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player->GetQuestStatus(46730) != QUEST_STATUS_REWARDED)
|
||||||
|
checktimer = 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
checktimer -= diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void AddSC_AssaultBrokenShore()
|
||||||
|
{
|
||||||
|
new npc_broken_shore_misc();
|
||||||
|
new npc_arcane_raven();
|
||||||
|
new npc_bs_legion_portal();
|
||||||
|
new go_bs_demoic_gates();
|
||||||
|
new player_scripts_for_start_assault();
|
||||||
|
};
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
-- remove second LFG queue, already gets triggered by end of scene
|
||||||
|
-- INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (227058, 'spell_q42740');
|
||||||
|
DELETE FROM spell_script_names WHERE spell_id = 227058 AND ScriptName = 'spell_q42740';
|
||||||
|
|
||||||
|
-- disable custom event (modified uwow Legion Invasion - Westfall/Barrens)
|
||||||
|
UPDATE game_event SET start_time = '0000-00-00 00:00:00', end_time = '0000-00-00 00:00:00', length = '1' WHERE eventEntry = 811;
|
||||||
|
|
||||||
|
-- disable rep gain from always spawned world quest npc 92128 (Felskorn Pilferer)
|
||||||
|
-- was: INSERT INTO creature_onkill_reputation (`creature_id`, `RewFaction`, `RewValue`, `MaxStanding`) VALUES (92128, 1948, 75, 7);
|
||||||
|
DELETE FROM creature_onkill_reputation WHERE creature_id = 92128 AND RewFaction = 1948;
|
||||||
|
|
||||||
|
-- fix droprate of greenies in Legion zones
|
||||||
|
-- was for world zones: UPDATE zone_loot_template SET ChanceOrQuestChance = 0.05 WHERE item = 463 AND entry IN (7334, 7502, 7503, 7541, 7543, 7558, 7578, 7637, 7656, 7731, 8392);
|
||||||
|
-- was for dungeons: UPDATE zone_loot_template SET ChanceOrQuestChance = 0.5 WHERE item = 463 AND entry IN (7546, 7588, 7672, 7673, 7787, 7796, 7805, 7812, 7855, 8017, 8025, 8026, 8040, 8079, 8262, 8277, 8443, 8570, 8596, 8625, 8646);
|
||||||
|
UPDATE zone_loot_template SET ChanceOrQuestChance = 2 WHERE item = 463 AND entry IN (7334, 7502, 7503, 7541, 7543, 7558, 7578, 7637, 7656, 7731, 8392);
|
||||||
|
UPDATE zone_loot_template SET ChanceOrQuestChance = 4 WHERE item = 463 AND entry IN (7546, 7588, 7672, 7673, 7787, 7796, 7805, 7812, 7855, 8017, 8025, 8026, 8040, 8079, 8262, 8277, 8443, 8570, 8596, 8625, 8646);
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
BrokenShore
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ScriptMgr.h"
|
||||||
|
#include "ScriptedCreature.h"
|
||||||
|
|
||||||
|
class instance_AssaultBrokenShore : public InstanceMapScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
instance_AssaultBrokenShore() : InstanceMapScript("instance_AssaultBrokenShore", 1666) { }
|
||||||
|
|
||||||
|
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||||
|
{
|
||||||
|
return new instance_AssaultBrokenShore_InstanceMapScript(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct instance_AssaultBrokenShore_InstanceMapScript : public InstanceScript
|
||||||
|
{
|
||||||
|
instance_AssaultBrokenShore_InstanceMapScript(Map* map) : InstanceScript(map) {}
|
||||||
|
|
||||||
|
WorldLocation loc_res_pla; // for respawn
|
||||||
|
|
||||||
|
GuidList FriendlyMisc;
|
||||||
|
|
||||||
|
ObjectGuid Arganot_guid;
|
||||||
|
ObjectGuid Illidan_guid;
|
||||||
|
ObjectGuid Mefistrot_guid;
|
||||||
|
|
||||||
|
void Initialize() override
|
||||||
|
{
|
||||||
|
Arganot_guid.Clear();
|
||||||
|
Mefistrot_guid.Clear();
|
||||||
|
Illidan_guid.Clear();
|
||||||
|
|
||||||
|
FriendlyMisc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldLocation* GetClosestGraveYard(float x, float y, float z) override
|
||||||
|
// OnPlayerDeath
|
||||||
|
{
|
||||||
|
// Init data
|
||||||
|
loc_res_pla.Relocate(x, y, z);
|
||||||
|
loc_res_pla.SetMapId(1666);
|
||||||
|
|
||||||
|
return &loc_res_pla;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnUnitDeath(Unit* creature) override
|
||||||
|
{
|
||||||
|
switch (creature->GetEntry())
|
||||||
|
{
|
||||||
|
case 116291:
|
||||||
|
updateCriteriaForPlayers(56500);
|
||||||
|
break;
|
||||||
|
case 118551:
|
||||||
|
updateCriteriaForPlayers(56780);
|
||||||
|
break;
|
||||||
|
// 1
|
||||||
|
case 118654:
|
||||||
|
case 118453:
|
||||||
|
case 118886:
|
||||||
|
case 118456:
|
||||||
|
updateCriteriaForPlayers(56697);
|
||||||
|
break;
|
||||||
|
// 3
|
||||||
|
case 120511:
|
||||||
|
case 118711:
|
||||||
|
case 118644:
|
||||||
|
case 118647:
|
||||||
|
case 118645:
|
||||||
|
case 118656:
|
||||||
|
case 118655:
|
||||||
|
case 118708:
|
||||||
|
case 118658:
|
||||||
|
case 118563:
|
||||||
|
case 118659:
|
||||||
|
case 118646:
|
||||||
|
case 118650:
|
||||||
|
case 118648:
|
||||||
|
case 118652:
|
||||||
|
case 118653:
|
||||||
|
case 118707:
|
||||||
|
case 118688:
|
||||||
|
case 118457:
|
||||||
|
case 118416:
|
||||||
|
for (uint8 i = 0; i < urand(2, 3); i++)
|
||||||
|
updateCriteriaForPlayers(56779);
|
||||||
|
break;
|
||||||
|
case 120746:
|
||||||
|
onScenarionNextStep(8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPlayerEnter(Player* player) override
|
||||||
|
{
|
||||||
|
if (!player)
|
||||||
|
return;
|
||||||
|
|
||||||
|
player->CastSpell(player, 240155);
|
||||||
|
|
||||||
|
player->AddDelayedEvent(5000, [player]() -> void
|
||||||
|
{
|
||||||
|
player->CastSpell(player, 243303); // summon
|
||||||
|
|
||||||
|
std::list<Creature*> trash;
|
||||||
|
GetCreatureListWithEntryInGrid(trash, player, 118412, 50.0f);
|
||||||
|
for (std::list<Creature*>::iterator itr = trash.begin(); itr != trash.end(); ++itr)
|
||||||
|
(*itr)->CastSpell(*itr, 243303); // summon
|
||||||
|
|
||||||
|
player->AddDelayedEvent(4000, [player]() -> void
|
||||||
|
{
|
||||||
|
player->RemoveAura(240188);
|
||||||
|
player->CreateConversation(4526);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCriteriaForPlayers(uint32 objective)
|
||||||
|
{
|
||||||
|
Map::PlayerList const &PlList = instance->GetPlayers();
|
||||||
|
|
||||||
|
if (PlList.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
|
||||||
|
if (Player* player = i->getSource())
|
||||||
|
{
|
||||||
|
player->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, objective);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCreatureCreate(Creature* creature) override
|
||||||
|
{
|
||||||
|
switch (creature->GetEntry())
|
||||||
|
{
|
||||||
|
case 119133:
|
||||||
|
case 118412:
|
||||||
|
case 121232:
|
||||||
|
case 118966:
|
||||||
|
case 121146:
|
||||||
|
case 118969:
|
||||||
|
case 118945:
|
||||||
|
case 118444:
|
||||||
|
FriendlyMisc.push_back(creature->GetGUID());
|
||||||
|
break;
|
||||||
|
case 118551:
|
||||||
|
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC);
|
||||||
|
creature->SetVisible(false);
|
||||||
|
Arganot_guid = creature->GetGUID();
|
||||||
|
break;
|
||||||
|
case 119130:
|
||||||
|
Illidan_guid = creature->GetGUID();
|
||||||
|
break;
|
||||||
|
case 120746:
|
||||||
|
creature->SetVisible(false);
|
||||||
|
Mefistrot_guid = creature->GetGUID();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onScenarionNextStep(uint32 newStep) override
|
||||||
|
{
|
||||||
|
switch (newStep)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if (Creature* arganot = instance->GetCreature(Arganot_guid))
|
||||||
|
{
|
||||||
|
arganot->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC);
|
||||||
|
arganot->SetVisible(true);
|
||||||
|
arganot->GetMotionMaster()->Clear();
|
||||||
|
if (Creature* illidan = instance->GetCreature(Illidan_guid))
|
||||||
|
{
|
||||||
|
arganot->GetMotionMaster()->MovePoint(0, illidan->GetPositionX(), illidan->GetPositionY(), illidan->GetPositionZ());
|
||||||
|
illidan->AI()->AttackStart(arganot);
|
||||||
|
arganot->AI()->AttackStart(illidan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto guid : FriendlyMisc)
|
||||||
|
{
|
||||||
|
if (Creature* cre = instance->GetCreature(guid))
|
||||||
|
{
|
||||||
|
cre->GetMotionMaster()->Clear();
|
||||||
|
cre->GetMotionMaster()->MovePath(11322709, false, irand(-8, 8), irand(-8, 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: // custom
|
||||||
|
{
|
||||||
|
for (auto guid : FriendlyMisc)
|
||||||
|
{
|
||||||
|
if (Creature* cre = instance->GetCreature(guid))
|
||||||
|
{
|
||||||
|
cre->GetMotionMaster()->Clear();
|
||||||
|
cre->GetMotionMaster()->MovePath(11322707, false, irand(-8, 8), irand(-8, 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
Map::PlayerList const &PlList = instance->GetPlayers();
|
||||||
|
|
||||||
|
if (PlList.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
|
||||||
|
if (Player* player = i->getSource())
|
||||||
|
{
|
||||||
|
player->CreateConversation(4829);
|
||||||
|
player->AddDelayedEvent(5000, [player]() -> void
|
||||||
|
{
|
||||||
|
player->CreateConversation(4831);
|
||||||
|
});
|
||||||
|
|
||||||
|
player->AddDelayedEvent(7000, [player]() -> void
|
||||||
|
{
|
||||||
|
player->CreateConversation(4832);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto guid : FriendlyMisc)
|
||||||
|
{
|
||||||
|
if (Creature* cre = instance->GetCreature(guid))
|
||||||
|
{
|
||||||
|
if (cre->GetPositionZ() <= 34.36f && cre->GetPositionX() <= -1524.42f) // only on the shore
|
||||||
|
{
|
||||||
|
cre->GetMotionMaster()->Clear();
|
||||||
|
cre->GetMotionMaster()->MovePath(11322705, false, irand(-5, 5), irand(-5, 5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
Map::PlayerList const &PlList = instance->GetPlayers();
|
||||||
|
|
||||||
|
if (PlList.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
|
||||||
|
if (Player* player = i->getSource())
|
||||||
|
{
|
||||||
|
player->CreateConversation(4887);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto guid : FriendlyMisc)
|
||||||
|
{
|
||||||
|
if (Creature* cre = instance->GetCreature(guid))
|
||||||
|
{
|
||||||
|
if (cre->GetPositionY() >= 3144.0f)
|
||||||
|
{
|
||||||
|
cre->GetMotionMaster()->Clear();
|
||||||
|
cre->GetMotionMaster()->MovePath(11322706, false, irand(-5, 5), irand(-5, 5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
if (Creature* mefistrot = instance->GetCreature(Mefistrot_guid))
|
||||||
|
{
|
||||||
|
mefistrot->SetVisible(true);
|
||||||
|
mefistrot->CreateConversation(4870);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
Map::PlayerList const &PlList = instance->GetPlayers();
|
||||||
|
|
||||||
|
if (PlList.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
|
||||||
|
if (Player* player = i->getSource())
|
||||||
|
{
|
||||||
|
player->AddDelayedEvent(4000, [player]() -> void
|
||||||
|
{
|
||||||
|
player->CreateConversation(4892);
|
||||||
|
player->CompleteQuest(46734);
|
||||||
|
});
|
||||||
|
|
||||||
|
player->AddDelayedEvent(4000, [player]() -> void
|
||||||
|
{
|
||||||
|
player->CastSpell(player, 243824);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddSC_instance_AssaultBrokenShore()
|
||||||
|
{
|
||||||
|
new instance_AssaultBrokenShore();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user