View Single Post
  #10  
Old 07-25-2008, 06:04 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

After more testing, it seems like recast delay is working properly, but is picky about what kind of spells you set to which type:

From MobAI.cpp:
Code:
const int SpellType_Nuke=1;
const int SpellType_Heal=2;
const int SpellType_Root=4;
const int SpellType_Buff=8;
const int SpellType_Escape=16;
const int SpellType_Pet=32;
const int SpellType_Lifetap=64;
const int SpellType_Snare=128;
const int SpellType_DOT=256;
This list includes most of the spell types people might like to use for NPCs, but it seems like some just don't fit in anywhere. I would like to add a new one for in combat buffs to be used for spells like Yaulp and for Melee Disciplines. Yaulp works ok as a normal buff, but it is a little bit pointless to have NPCs constantly recasting that spell on themselves. They really should only use it during combat, but there currently isn't any way for that to work properly. The main reason I want to add this new category is for Disciplines.

It seems that when you set a discipline to type 1 (nuke), it will cast properly, but since it is self only, it apparently doesn't pass all of the checks for being a "nuke" spell. So, I think the problem is that it is never reaching the point where it is supposed to check the recast delay setting. Maybe the nuke one could just be edited to allow this, or a whole new type could be added:

Code:
const int SpellType_Combat_Buff=512;
Then, I think that would need to be added here in the MobAI.cpp:
Code:
const int SpellTypes_Detrimental = SpellType_Nuke|SpellType_Root|SpellType_Lifetap|SpellType_Snare|SpellType_DOT|SpellType_Combat_Buff;
const int SpellTypes_Beneficial = SpellType_Heal|SpellType_Buff|SpellType_Escape|SpellType_Pet;
Looking at some of the examples, we have:

Buff
Code:
					case SpellType_Buff: {
						if (
							(spells[AIspells[i].spellid].targettype == ST_Target || tar == this)
							&& tar->DontBuffMeBefore() < Timer::GetCurrentTime()
							&& !tar->IsImmuneToSpell(AIspells[i].spellid, this)
							&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
							&& !(tar->IsPet() && tar->GetOwner()->IsClient() && this != tar)	//no buffing PC's pets, but they can buff themself
							) {
							AIDoSpellCast(i, tar, mana_cost, &tar->pDontBuffMeBefore);
							return true;
						}
						break;
					}
Nuke
Code:
					case SpellType_Nuke: {
						if (
							manaR >= 40 && (rand()%100) < 50
							&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
							) {
							if(!checked_los) {
								if(!CheckLosFN(tar))
									return(false);	//cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call
								checked_los = true;
							}
							AIDoSpellCast(i, tar, mana_cost);
							return true;
						}
						break;
					}
And, I am just guessing that putting Disciplines in Nuke is failing and going to the following:

Code:
					default: {
						cout<<"Error: Unknown spell type in AICastSpell. caster:"<<this->GetName()<<" type:"<<AIspells[i].type<<" slot:"<<i<<endl;
						break;
					}
But, the actual checks after a successful cast seem to be here:
Code:
	//this gets called from InterruptSpell() for failure or SpellFinished() for success
	void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, int8 slot) {
		if (slot == 1) {
			int32 recovery_time = 0;
			if (iCastSucceeded) {
				if (casting_spell_AIindex < MAX_AISPELLS) {
						recovery_time += spells[AIspells[casting_spell_AIindex].spellid].recovery_time;
						if (AIspells[casting_spell_AIindex].recast_delay >= 0){
							if (AIspells[casting_spell_AIindex].recast_delay <1000)
								AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + (AIspells[casting_spell_AIindex].recast_delay*1000);
	}
						else
							AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + spells[AIspells[casting_spell_AIindex].spellid].recast_time;
				}
				if (!IsEngaged())
					recovery_time += RandomTimer(2000, 3000);
				if (recovery_time < AIautocastspell_timer->GetSetAtTrigger())
					recovery_time = AIautocastspell_timer->GetSetAtTrigger();
				AIautocastspell_timer->Start(recovery_time, false);
			}
			else
				AIautocastspell_timer->Start(800, false);
			casting_spell_AIindex = MAX_AISPELLS;
		}
}
So, I think that the only other thing that might need to be added is a new section for Combat_Buffs. Though, I am not sure if I need to add anything somewhere else to get it to work. I think that by copying the settings for buff and calling it Combat_Buff, and then adding Combat_Buff to detrimental spells, it will allow for NPCs to only cast these types of buffs during combat, which is the opposite from normal buffs.

Code:
					case SpellType_Combat_Buff: {
						if (
							(spells[AIspells[i].spellid].targettype == ST_Target || tar == this)
							&& tar->DontBuffMeBefore() < Timer::GetCurrentTime()
							&& !tar->IsImmuneToSpell(AIspells[i].spellid, this)
							&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
							&& !(tar->IsPet() && tar->GetOwner()->IsClient() && this != tar)	//no buffing PC's pets, but they can buff themself
							) {
							AIDoSpellCast(i, tar, mana_cost, &tar->pDontBuffMeBefore);
							return true;
						}
						break;
					}
I guess I will test this out on my server and just cross my fingers that I don't break anything lol. I am such a gimpy coder, but this makes at least a little sense to me... If it works, I will post it in server code submissions with better details on how to add this code in, even though everything should already be here.

If anyone else has any input on getting this to work the way I want, I would love to hear it
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote