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