Fehler #17378
geschlossenFehler #3772: [Heroische Instanzen] Wotlk - Sammelticket
Fehler #4468: [Oculus][HC] Sammelticket
[Oculus] Magierlord Urom - Teleport und Spawn der Wellen
Von 1337 vor fast 9 Jahren hinzugefügt. Vor fast 8 Jahren aktualisiert.
Magierlord Urom im Oculus teleportiert sich nun nicht mehr mehrfach hintereinander, gleichzeitig zu mehreren Plattformen.
Beschreibung
Das Teleportverhalten und der damit in Zusammenhang stehende Spawn der Wellen funktionieren nicht korrekt.
Es spawnen oft zwei Wellen auf einer Platform und der Boss teleportiert sich direkt zur letzten Platform. Teilweise spawnen die Wellen auch auf der nächsten Platform und sind mit der Gruppe in Combat (laufen dann oft durch die Luft auf die Platform, auf der die Gruppe ist). Manchmal teleportiert sich der Boss auch direkt in die Mitte und ist mit der Gruppe in Combat - fliegt dann ebenfalls (wenn man Glück hat) zur Platform mit der Gruppe zurück.
Dies führt auch oft zu Combat Bugs.
Von Rushor vor fast 9 Jahren aktualisiert
- Status wurde von Bestätigt zu Testbereit geändert
nur noch 1 cast
Von 1337 vor fast 9 Jahren aktualisiert
Falls jemand weiss wie man es gezielt reproduzieren kann, wäre auch toll. Sonst wird man es wohl einfach Live nehmen müssen.
Von Rushor vor fast 9 Jahren aktualisiert
lokal war es vorher immer buggy nach folgenden schritten:
- outfight boss nähern (aber den kampf nicht durch meleehits starten)
- spott vom pala wirken
- doppelte spawnanzahl erhalten + doppelte textausgabe vom boss im chat
Von Shienor vor fast 9 Jahren aktualisiert
- Status wurde von Testbereit zu Ready geändert
- Update Text Deutsch aktualisiert (Vergleich)
Von Rushor vor mehr als 8 Jahren aktualisiert
welche attacke wurde auf dem boss zuerst ausgeführt?
Von erimioa vor mehr als 8 Jahren aktualisiert
einmal hatte ich hand der abrechnung, beim nächsten mal richturteil der weisheit. Und dann hatte er gebugt. Mussten nicht mehr zur dritten plattform, weil er schon da die letzten beiden wellen hatte und dann zu uns rüber geflogen ist.
Ich glaube nicht dass mein code aktuell ist, aber im alten steht noch
if (instance->GetData(DATA_UROM_PLATAFORM) != 3)
instance->SetData(DATA_UROM_PLATAFORM, instance->GetData(DATA_UROM_PLATAFORM)+1);
drin, in void EnterCombat(). Sicher bin ich mir nicht, aber wenn er mehrmals infight kommt, z.B. weil er durch beginnen des wegportens raus geht, dann beim nächsten aoe treffer oder so wiede rinfight und co, dass es dadurch vorkommnt?
Müsste detaullierter getestet werden, wann er outfight kommt, weil ich sehe das irgendwie nicht im script.
Von Rushor vor mehr als 8 Jahren aktualisiert
in damage taken ist er gegen bestimmte attacken nicht komplett immun und führt die teleports dann mehrfach hintereinander aus
tc ist einfach scheiße
Von erimioa vor mehr als 8 Jahren aktualisiert
es gibt doch sicherlich einen weg den gegen alle Spells imun zu machen, dessen caster ein spieler ist. Dann sollte es sich haben ^^
Von Rushor vor mehr als 8 Jahren aktualisiert
da fällt mir auch gerade ein, er darf gar nicht immun sein, da er sonst nicht anfängt den teleportcast zu wirken :D
/* REWRITTEN FROM SCRATCH BY PUSSYWIZARD, IT OWNS NOW! */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "oculus.h" #include "SpellInfo.h" enum Spells { SPELL_EVOCATION = 51602, SPELL_SUMMON_MENAGERIE_1 = 50476, SPELL_SUMMON_MENAGERIE_2 = 50495, SPELL_SUMMON_MENAGERIE_3 = 50496, SPELL_TELEPORT = 51112, SPELL_FROSTBOMB = 51103, SPELL_TIME_BOMB_N = 51121, SPELL_TIME_BOMB_H = 59376, SPELL_EMPOWERED_ARCANE_EXPLOSION_N = 51110, SPELL_EMPOWERED_ARCANE_EXPLOSION_H = 59377, }; #define SPELL_EMPOWERED_ARCANE_EXPLOSION DUNGEON_MODE(SPELL_EMPOWERED_ARCANE_EXPLOSION_N, SPELL_EMPOWERED_ARCANE_EXPLOSION_H) #define SPELL_TIME_BOMB DUNGEON_MODE(SPELL_TIME_BOMB_N, SPELL_TIME_BOMB_H) enum UromNPCs { NPC_PHANTASMAL_CLOUDSCRAPER = 27645, NPC_PHANTASMAL_MAMMOTH = 27642, NPC_PHANTASMAL_WOLF = 27644, NPC_PHANTASMAL_AIR = 27650, NPC_PHANTASMAL_FIRE = 27651, NPC_PHANTASMAL_WATER = 27653, NPC_PHANTASMAL_MURLOC = 27649, NPC_PHANTASMAL_NAGAL = 27648, NPC_PHANTASMAL_OGRE = 27647, }; enum Events { EVENT_FROSTBOMB = 1, EVENT_TELEPORT_TO_CENTER = 2, EVENT_TELE_BACK = 3, EVENT_TIME_BOMB = 4, }; enum Yells { SAY_SUMMON_1 = 0, SAY_SUMMON_2 = 1, SAY_SUMMON_3 = 2, SAY_AGGRO = 3, EMOTE_ARCANE_EXPLOSION = 4, SAY_ARCANE_EXPLOSION = 5, SAY_DEATH = 6, SAY_PLAYER_KILL = 7 }; float summons[3][4] = { {NPC_PHANTASMAL_AIR, NPC_PHANTASMAL_AIR, NPC_PHANTASMAL_WATER, NPC_PHANTASMAL_FIRE}, {NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_NAGAL, NPC_PHANTASMAL_MURLOC}, {NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_MAMMOTH, NPC_PHANTASMAL_WOLF} }; float cords[4][4] = { {1177.47f, 937.722f, 527.405f, 2.21657f}, {968.66f, 1042.53f, 527.32f, 0.077f}, {1164.02f, 1170.85f, 527.321f, 3.66f}, {1118.31f, 1080.377f, 508.361f, 4.25f} }; class boss_urom : public CreatureScript { public: boss_urom() : CreatureScript("boss_urom") { } CreatureAI* GetAI(Creature* pCreature) const { return new boss_uromAI (pCreature); } struct boss_uromAI : public ScriptedAI { boss_uromAI(Creature *c) : ScriptedAI(c) { pInstance = c->GetInstanceScript(); } InstanceScript* pInstance; EventMap events; bool lock; float x,y,z; int32 releaseLockTimer; uint8 GetPhaseByCurrentPosition() { for (uint8 i=0; i<4; ++i) if (me->GetDistance(cords[i][0], cords[i][1], cords[i][2]) < 20.0f) return i; return 0; } void Reset() { if (pInstance) { pInstance->SetData(DATA_UROM, NOT_STARTED); if( pInstance->GetData(DATA_VAROS) != DONE ) me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); else me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } me->CastSpell(me, SPELL_EVOCATION, true); events.Reset(); lock = false; x,y,z = 0.0f; releaseLockTimer = 0; me->ApplySpellImmune(0, IMMUNITY_ID, 49838, true); } void EnterCombat(Unit* who) { if( lock ) return; uint8 phase = GetPhaseByCurrentPosition(); if( phase == 3 ) { Talk(SAY_AGGRO); if( pInstance ) pInstance->SetData(DATA_UROM, IN_PROGRESS); me->SetInCombatWithZone(); me->SetHomePosition(cords[0][0], cords[0][1], cords[0][2], cords[0][3]); if( me->FindCurrentSpellBySpellId(SPELL_EVOCATION) ) me->InterruptNonMeleeSpells(false); events.RescheduleEvent(EVENT_FROSTBOMB, urand(7000, 11000)); events.RescheduleEvent(EVENT_TELEPORT_TO_CENTER, urand(30000, 35000)); events.RescheduleEvent(EVENT_TIME_BOMB, urand(20000, 25000)); } else { lock = true; switch( phase ) { case 0: Talk(SAY_SUMMON_1); me->InterruptNonMeleeSpells(false); me->CastSpell(me, SPELL_SUMMON_MENAGERIE_1, false); break; case 1: Talk(SAY_SUMMON_2); me->InterruptNonMeleeSpells(false); me->CastSpell(me, SPELL_SUMMON_MENAGERIE_2, false); break; case 2: Talk(SAY_SUMMON_3); me->InterruptNonMeleeSpells(false); me->CastSpell(me, SPELL_SUMMON_MENAGERIE_3, false); break; } } } void AttackStart(Unit* who) { if( lock ) return; if (me->GetDistance(1103.0f, 1049.0f, 510.0f) < 55.0f) ScriptedAI::AttackStart(who); } void JustSummoned(Creature* pSummon) { pSummon->SetInCombatWithZone(); if( Unit* v = pSummon->SelectVictim() ) if( pSummon->AI() ) pSummon->AI()->AttackStart(v); } void LeaveCombat() { me->RemoveAllAuras(); me->DeleteThreatList(); me->CombatStop(true); me->LoadCreaturesAddon(true); me->SetLootRecipient(NULL); me->ResetPlayerDamageReq(); } void JustDied(Unit* killer) { Talk(SAY_DEATH); if (pInstance) pInstance->SetData(DATA_UROM, DONE); } void KilledUnit(Unit *victim) { Talk(SAY_PLAYER_KILL); } void SpellHit(Unit* caster, const SpellInfo* spell) { switch( spell->Id ) { case SPELL_SUMMON_MENAGERIE_1: case SPELL_SUMMON_MENAGERIE_2: case SPELL_SUMMON_MENAGERIE_3: { me->DestroyForNearbyPlayers(); uint8 phase = GetPhaseByCurrentPosition(); for( uint8 i=0; i<4; ++i ) me->SummonCreature(summons[phase][i], cords[phase][0] + ((i%2) ? 4.0f : -4.0f), cords[phase][1] + (i<2 ? 4.0f : -4.0f), cords[phase][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN, 300000); me->SetHomePosition(cords[phase+1][0], cords[phase+1][1], cords[phase+1][2], cords[phase+1][3]); LeaveCombat(); me->CastSpell(me, SPELL_EVOCATION, true); releaseLockTimer = 1; } break; case SPELL_TELEPORT: me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); me->StopMoving(); me->SetControlled(true, UNIT_STATE_ROOT); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetCanFly(true); me->SetDisableGravity(true); me->NearTeleportTo(1103.69f, 1048.76f, 512.279f, 1.16f); Talk(SAY_ARCANE_EXPLOSION); Talk(EMOTE_ARCANE_EXPLOSION); me->CastSpell(me, SPELL_EMPOWERED_ARCANE_EXPLOSION, false); events.RescheduleEvent(EVENT_TELE_BACK, DUNGEON_MODE(9000, 7000)); default: break; } } void MoveInLineOfSight(Unit* who) {} void UpdateAI(uint32 diff) { if( releaseLockTimer ) { if( releaseLockTimer >= 5000 ) { lock = false; if (me->IsInCombat()) { LeaveCombat(); me->CastSpell(me, SPELL_EVOCATION, true); } releaseLockTimer = 0; } else releaseLockTimer += diff; } if( !UpdateVictim() ) return; events.Update(diff); if( me->HasUnitState(UNIT_STATE_CASTING) ) return; DoMeleeAttackIfReady(); switch( events.GetEvent() ) { case 0: break; case EVENT_FROSTBOMB: if( Unit* v = me->GetVictim() ) me->CastSpell(v, SPELL_FROSTBOMB, false); events.RepeatEvent(urand(7000,11000)); break; case EVENT_TIME_BOMB: if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true) ) me->CastSpell(target, SPELL_TIME_BOMB, false); events.RepeatEvent(urand(20000, 25000)); break; case EVENT_TELEPORT_TO_CENTER: x = me->GetPositionX(); y = me->GetPositionY(); z = me->GetPositionZ(); me->CastSpell(me, SPELL_TELEPORT, false); events.RepeatEvent(urand(25000,30000)); events.DelayEvents(10000); break; case EVENT_TELE_BACK: me->GetMotionMaster()->MoveIdle(); me->DisableSpline(); me->SetCanFly(false); me->SetDisableGravity(false); me->NearTeleportTo(x, y, z, 0.0f); me->SetControlled(false, UNIT_STATE_ROOT); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->GetMotionMaster()->MoveChase(me->GetVictim()); events.PopEvent(); break; } } void EnterEvadeMode() { me->SetCanFly(false); me->SetDisableGravity(false); me->SetControlled(false, UNIT_STATE_ROOT); ScriptedAI::EnterEvadeMode(); } }; }; void AddSC_boss_urom() { new boss_urom(); }
by sunwell
Von erimioa vor mehr als 8 Jahren aktualisiert
for (uint8 i = 0; i<4; ++i) iiiiiiiiieeeeeeeehhhhhhhh codestyle
if (me->GetDistance(cords[i][0], cords[i][1], cords[i][2]) < 20.0f) XY coordinaten reichen auch aus, spart rechenzeit fürn server und ist weniger Fehleranfällig
if (pInstance->GetData(DATA_VAROS) != DONE)
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
else
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
es gibt meines wissens 2 non attackable flags, in anderen scripts mussten immer beide gesetzt werden. Wurde das inzwischen gefixt oder fehlen die hier?
me->ApplySpellImmune(0, IMMUNITY_ID, 49838, true); codestyle, außerdem müsste doch eher der spell in conditions eingetragen bekommen haben, welche NPCs er betreffen darf, statt umgekehrt. Zumindest hatte ich das mal vor gefühlt einem Jahrzent dort so gefixt gehabt, weile s ja auch sinnvoller ist. Wer weis was da für Trigger sonst rumgimpen die geschockfrostet werden.
uint8 GetPhaseByCurrentPosition()
{
for (uint8 i = 0; i<4; ++i)
if (me->GetDistance(cords[i][0], cords[i][1], cords[i][2]) < 20.0f)
return i;
return 0;
}
wenn er nirgends richtig steht, wird das Event von der ersten Position getriggert? Da würde ich noch ein saver einbauen für den Reset. Klar ist das return 0 nur dafür da kein compile warning zu bekommen, aber wenn da was nicht stimmt, würden halt z.B. adds doppelt spawnen.
switch (phase)
{
case 0:
Talk(SAY_SUMMON_1);
me->InterruptNonMeleeSpells(false);
me->CastSpell(me, SPELL_SUMMON_MENAGERIE_1, false);
break;
case 1:
Talk(SAY_SUMMON_2);
me->InterruptNonMeleeSpells(false);
me->CastSpell(me, SPELL_SUMMON_MENAGERIE_2, false);
break;
case 2:
Talk(SAY_SUMMON_3);
me->InterruptNonMeleeSpells(false);
me->CastSpell(me, SPELL_SUMMON_MENAGERIE_3, false);
break;
}
das me->InterruptNonMeleeSpells(false); kann man aus der switch raus nehmen und allgemein in die übergeordnete else packen.
if (me->GetDistance(1103.0f, 1049.0f, 510.0f) < 55.0f) könnte man genauso wie die anderen positions auch ausgliedern und auch hier sollte eine xy abfrage reichen.
void SpellHit(Unit* caster, const SpellInfo* spell)
{
...
LeaveCombat();
ich persönlich hätte es wohl eher in eine
if (!lock)
LeaveCombat();
außerhalb der switch gepackt, eben um hier das enter combat durch durch spätere/andere bla treffer zu verhindern. Ich stelle mir auch Dots gut vor. Weil falls die NACH dem beginnen vom port spell casten auf ihn drauf kommen sollten, bleiben sie auch drauf.
default:
break;
unnötig
urand(7000, 11000) und fortfolgende codestyle? Hat sich da was geändert, seitdem ich weig bin? Jahrelang predigt trinity IN_MILLISECONDS zu nutzen und jetzt nach ein paar Monate alles weg :)
Von Rushor vor mehr als 8 Jahren aktualisiert
- Zugewiesen an wurde auf Rushor gesetzt
push 4 me
Von Rushor vor mehr als 8 Jahren aktualisiert
Bedeutung Live:
Der Bug wurde erfolgreich behoben und der Fix dazu befindet sich auf dem Spielserver. Sollte der Fehler weiterhin bestehen sollte ein neues Ticket ( https://redmine.rising-gods.de/projects/live/issues/new ) erstellt werden. Anmerkungen in dem alten abgewiesenen oder live genommenen Ticket werden ignoriert und gelöscht.