diff --git a/changelog.txt b/changelog.txt index 59b7a4e02..07c89cf11 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/01/2013 == +demonstar55: AA reuse timers now start when you hit the button and are reset upon failure +demonstar55: Instant Cast bard AAs can now be used while singing a song + == 03/30/2013 == demonstar55: Fixed most of the pet talking, all use StringIDs now. Pet now informs you when it taunts. diff --git a/zone/AA.cpp b/zone/AA.cpp index fdf5d6a95..05ffbb862 100644 --- a/zone/AA.cpp +++ b/zone/AA.cpp @@ -257,7 +257,7 @@ void Client::ActivateAA(aaID activate){ if(caa->action != aaActionNone) { if(caa->mana_cost > 0) { if(GetMana() < caa->mana_cost) { - Message(0, "Not enough mana to use this skill."); + Message_StringID(13, INSUFFICIENT_MANA); return; } SetMana(GetMana() - caa->mana_cost); @@ -271,8 +271,7 @@ void Client::ActivateAA(aaID activate){ p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); } p_timers.Start(AATimerID + pTimerAAStart, timer_base); - time_t timestamp = time(NULL); - SendAATimer(AATimerID, static_cast(timestamp), static_cast(timestamp)); + SendAATimer(AATimerID, 0, 0); } } @@ -282,13 +281,30 @@ void Client::ActivateAA(aaID activate){ if(caa->reuse_time > 0) { uint32 timer_base = CalcAAReuseTimer(caa); + SendAATimer(AATimerID, 0, 0); + p_timers.Start(AATimerID + pTimerAAStart, timer_base); if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) { p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); } - - if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) - return; + // Bards can cast instant cast AAs while they are casting another song + if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { + if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { + //Reset on failed cast + SendAATimer(AATimerID, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + } else { + if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { + //Reset on failed cast + SendAATimer(AATimerID, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + } } else { diff --git a/zone/StringIDs.h b/zone/StringIDs.h index ba811ff90..6c44203b1 100644 --- a/zone/StringIDs.h +++ b/zone/StringIDs.h @@ -10,6 +10,7 @@ #define SPELL_DOES_NOT_WORK_PLANE 107 //This spell does not work on this plane. #define CANT_SEE_TARGET 108 //You cannot see your target. #define MGB_STRING 113 //The next group buff you cast will hit all targets in range. +#define ABILITY_FAILED 116 //Your ability failed. Timer has been reset. #define ESCAPE 114 //You escape from combat, hiding yourself from view. #define TARGET_TOO_FAR 124 //Your target is too far away, get closer! #define PROC_TOOLOW 126 //Your will is not sufficient to command this weapon. diff --git a/zone/spells.cpp b/zone/spells.cpp index 5c85b4445..6ff8bb3b8 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -707,23 +707,26 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); } - if(casting_spell_type == 1 && IsClient()) //Rest AA Timer on failed cast - CastToClient()->GetPTimers().Clear(&database, casting_spell_timer); - + if(casting_spell_type == 1 && IsClient()) { //Rest AA Timer on failed cast + CastToClient()->SendAATimer(casting_spell_timer - pTimerAAStart, 0, 0xFFFFFF); + CastToClient()->Message_StringID(15,ABILITY_FAILED); + CastToClient()->GetPTimers().Clear(&database, casting_spell_timer); + } + ZeroCastingVars(); // resets all the state keeping stuff - + mlog(SPELLS__CASTING, "Spell %d has been interrupted.", spellid); - + if(!spellid) return; - + if (bardsong || IsBardSong(casting_spell_id)) _StopSong(); if(bard_song_mode) { return; } - + if(!message) message = IsBardSong(spellid) ? SONG_ENDS_ABRUPTLY : INTERRUPT_SPELL; @@ -1971,11 +1974,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 { CastToClient()->GetPTimers().Start(casting_spell_timer, casting_spell_timer_duration); mlog(SPELLS__CASTING, "Spell %d: Setting custom reuse timer %d to %d", spell_id, casting_spell_timer, casting_spell_timer_duration); - if(casting_spell_type == 1) //AA - { - time_t timestamp = time(NULL); - CastToClient()->SendAATimer((casting_spell_timer - pTimerAAStart), timestamp, timestamp); - } } else if(spells[spell_id].recast_time > 1000) { int recast = spells[spell_id].recast_time/1000;