Merge beaa405aa2df9cd09c33267053162c13182308c9 into 308a21e0e27792515afbdebc02e6d6cfef3f63e9

This commit is contained in:
Kemmler 2013-05-07 06:59:54 -07:00
commit c68873c22b
9 changed files with 82 additions and 9 deletions

4
.gitignore vendored
View File

@ -35,3 +35,7 @@ Build_64/
build_64/ build_64/
log/ log/
logs/ logs/
# Patch files
*.orig
*.rej

View File

@ -1862,12 +1862,12 @@ bool NPC::AI_IdleCastCheck() {
void Mob::StartEnrage() void Mob::StartEnrage()
{ {
// dont continue if already enraged // dont continue if already enraged
if (bEnraged) if (bEnraged || bInfuriated)
return; return;
if (SpecAttackTimers[SPECATK_ENRAGE] && !SpecAttackTimers[SPECATK_ENRAGE]->Check()) if (SpecAttackTimers[SPECATK_ENRAGE] && !SpecAttackTimers[SPECATK_ENRAGE]->Check())
return; return;
// see if NPC has possibility to enrage // see if NPC has possibility to enrage
if (!SpecAttacks[SPECATK_ENRAGE]) if (!SpecAttacks[SPECATK_ENRAGE] && !SpecAttacks[SPECATK_INFURIATE])
return; return;
// check if timer exists (should be true at all times) // check if timer exists (should be true at all times)
if (SpecAttackTimers[SPECATK_ENRAGE]) if (SpecAttackTimers[SPECATK_ENRAGE])
@ -1882,16 +1882,25 @@ void Mob::StartEnrage()
} }
// start the timer. need to call IsEnraged frequently since we dont have callback timers :-/ // start the timer. need to call IsEnraged frequently since we dont have callback timers :-/
SpecAttackTimers[SPECATK_ENRAGE]->Start(); SpecAttackTimers[SPECATK_ENRAGE]->Start();
if (SpecAttacks[SPECATK_ENRAGE]) {
bEnraged = true; bEnraged = true;
entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_START, GetCleanName()); entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_START, GetCleanName());
} else if (SpecAttacks[SPECATK_INFURIATE]) {
bInfuriated = true;
entity_list.MessageClose(this, true, 200, MT_NPCEnrage, "%1 is infuriated.", GetCleanName());
}
} }
void Mob::ProcessEnrage(){ void Mob::ProcessEnrage(){
if(IsEnraged()){ if(IsEnraged() || IsInfuriated()){
if(SpecAttackTimers[SPECATK_ENRAGE] && SpecAttackTimers[SPECATK_ENRAGE]->Check()){ if(SpecAttackTimers[SPECATK_ENRAGE] && SpecAttackTimers[SPECATK_ENRAGE]->Check()){
entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_END, GetCleanName());
SpecAttackTimers[SPECATK_ENRAGE]->Start(EnragedTimer); SpecAttackTimers[SPECATK_ENRAGE]->Start(EnragedTimer);
if(IsEnraged()) {
entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_END, GetCleanName());
bEnraged = false; bEnraged = false;
} else if(IsInfuriated()) {
entity_list.MessageClose(this, true, 200, MT_NPCEnrage,"%1 is no longer infuriated.", GetCleanName());
bInfuriated = false; }
} }
} }
} }
@ -1901,6 +1910,11 @@ bool Mob::IsEnraged()
return bEnraged; return bEnraged;
} }
bool Mob::IsInfuriated()
{
return bInfuriated;
}
bool Mob::Flurry() bool Mob::Flurry()
{ {
// this is wrong, flurry is extra attacks on the current target // this is wrong, flurry is extra attacks on the current target

View File

@ -382,6 +382,10 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
damage = -3; damage = -3;
mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack."); mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack.");
} }
if (IsInfuriated()) {
damage = -3;
mlog(COMBAT__DAMAGE, "I am infuriated, riposting attacks from all sides.");
}
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
// riposte // riposte

View File

@ -3752,6 +3752,9 @@ void Bot::AI_Process() {
// Stop attacking if the target is enraged // Stop attacking if the target is enraged
if(IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged()) if(IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged())
return; return;
// Stop attacking if the target is infuriated
if(IsEngaged() && GetTarget()->IsInfuriated())
return;
if(GetBotStance() == BotStancePassive) if(GetBotStance() == BotStancePassive)
return; return;
@ -4080,6 +4083,9 @@ void Bot::PetAIProcess() {
// Stop attacking while we are on a front arc and the target is enraged // Stop attacking while we are on a front arc and the target is enraged
if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged()) if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged())
return; return;
// Stop attacking while the target is infuriated
if(botPet->GetTarget()->IsInfuriated())
return;
if(botPet->Attack(GetTarget(), SLOT_PRIMARY)) // try the main hand if(botPet->Attack(GetTarget(), SLOT_PRIMARY)) // try the main hand
if (botPet->GetTarget()) // Do we still have a target? if (botPet->GetTarget()) // Do we still have a target?
@ -7842,6 +7848,11 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
damage = -3; damage = -3;
mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack."); mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack.");
} }
// same as enrage just no behind check needed.
if (IsInfuriated()) {
damage = -3;
mlog(COMBAT__DAMAGE, "I am infuriated, riposting attacks from all sides.");
}
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
// riposte // riposte

View File

@ -84,11 +84,11 @@ typedef enum { //focus types
/* /*
Used: Used:
b,d,f,g,j,m,n,o,p,r,t b,d,e,f,g,j,m,n,o,p,r,t
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,Q,R,S,T,U,W,Y A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,Q,R,S,T,U,W,Y
Unused: Unused:
a,c,e,h,k,l,q,s,u,v,w,x,y,z a,c,h,k,l,q,s,u,v,w,x,y,z
P,V,X P,V,X
*/ */
@ -96,6 +96,7 @@ enum {
SPECATK_NONE = 0, SPECATK_NONE = 0,
SPECATK_SUMMON, // S SPECATK_SUMMON, // S
SPECATK_ENRAGE, // E SPECATK_ENRAGE, // E
SPECATK_INFURIATE, // e
SPECATK_RAMPAGE, // R SPECATK_RAMPAGE, // R
SPECATK_AREA_RAMPAGE, // r SPECATK_AREA_RAMPAGE, // r
SPECATK_FLURRY, // F SPECATK_FLURRY, // F

View File

@ -1651,6 +1651,9 @@ void Merc::AI_Process() {
// Stop attacking if the target is enraged // Stop attacking if the target is enraged
if(IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged()) if(IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged())
return; return;
// stop attacking if the target is infuriated
if(IsEngaged() && GetTarget()->IsInfuriated())
return;
//TODO: Implement Stances. //TODO: Implement Stances.
/*if(GetBotStance() == BotStancePassive) /*if(GetBotStance() == BotStancePassive)
return;*/ return;*/

View File

@ -648,6 +648,7 @@ public:
void StartEnrage(); void StartEnrage();
void ProcessEnrage(); void ProcessEnrage();
bool IsEnraged(); bool IsEnraged();
bool IsInfuriated();
void Taunt(NPC* who, bool always_succeed, float chance_bonus = 0); void Taunt(NPC* who, bool always_succeed, float chance_bonus = 0);
virtual void AI_Init(); virtual void AI_Init();
@ -945,6 +946,7 @@ protected:
char lastname[64]; char lastname[64];
bool bEnraged; bool bEnraged;
bool bInfuriated;
Timer *SpecAttackTimers[SPECATK_MAXNUM]; Timer *SpecAttackTimers[SPECATK_MAXNUM];
bool destructibleobject; bool destructibleobject;

View File

@ -1447,6 +1447,9 @@ void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool rem
case 'E': case 'E':
SpecAttacks[SPECATK_ENRAGE] = (remove ? false : true); SpecAttacks[SPECATK_ENRAGE] = (remove ? false : true);
break; break;
case 'e':
SpecAttacks[SPECATK_INFURIATE] = (remove ? false : true);
break;
case 'F': case 'F':
SpecAttacks[SPECATK_FLURRY] = (remove ? false : true); SpecAttacks[SPECATK_FLURRY] = (remove ? false : true);
break; break;
@ -1592,6 +1595,10 @@ bool Mob::HasNPCSpecialAtk(const char* parse) {
if (!SpecAttacks[SPECATK_ENRAGE]) if (!SpecAttacks[SPECATK_ENRAGE])
HasAllAttacks = false; HasAllAttacks = false;
break; break;
case 'e':
if (!SpecAttacks[SPECATK_INFURIATE])
HasAllAttacks = false;
break;
case 'F': case 'F':
if (!SpecAttacks[SPECATK_FLURRY]) if (!SpecAttacks[SPECATK_FLURRY])
HasAllAttacks = false; HasAllAttacks = false;

View File

@ -5010,6 +5010,32 @@ XS(XS_Mob_IsEnraged)
XSRETURN(1); XSRETURN(1);
} }
XS(XS_Mob_IsInfuriated); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_IsInfuriated)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Mob::IsInfuriated(THIS)");
{
Mob * THIS;
bool RETVAL;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Mob *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Mob");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->IsInfuriated();
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_Mob_GetReverseFactionCon); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_GetReverseFactionCon); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetReverseFactionCon) XS(XS_Mob_GetReverseFactionCon)
{ {
@ -8267,6 +8293,7 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "IsStunned"), XS_Mob_IsStunned, file, "$"); newXSproto(strcpy(buf, "IsStunned"), XS_Mob_IsStunned, file, "$");
newXSproto(strcpy(buf, "StartEnrage"), XS_Mob_StartEnrage, file, "$"); newXSproto(strcpy(buf, "StartEnrage"), XS_Mob_StartEnrage, file, "$");
newXSproto(strcpy(buf, "IsEnraged"), XS_Mob_IsEnraged, file, "$"); newXSproto(strcpy(buf, "IsEnraged"), XS_Mob_IsEnraged, file, "$");
newXSproto(strcpy(buf, "IsInfuriated"), XS_Mob_IsInfuriated, file, "$");
newXSproto(strcpy(buf, "GetReverseFactionCon"), XS_Mob_GetReverseFactionCon, file, "$$"); newXSproto(strcpy(buf, "GetReverseFactionCon"), XS_Mob_GetReverseFactionCon, file, "$$");
newXSproto(strcpy(buf, "IsAIControlled"), XS_Mob_IsAIControlled, file, "$"); newXSproto(strcpy(buf, "IsAIControlled"), XS_Mob_IsAIControlled, file, "$");
newXSproto(strcpy(buf, "GetAggroRange"), XS_Mob_GetAggroRange, file, "$"); newXSproto(strcpy(buf, "GetAggroRange"), XS_Mob_GetAggroRange, file, "$");