Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Bug Reports

Development::Bug Reports Post detailed bug reports and what you would like to see next in the emu here.

Reply
 
Thread Tools Display Modes
  #1  
Old 07-15-2008, 10:39 PM
moydock
Discordant
 
Join Date: Jun 2005
Posts: 286
Default

Yeah mines working fine. I'm not on the latest build, but fairly recent.
It's in seconds for me. For example, the heal I just tested:
ID: 367
npc_spells_id: 6
spellid: 200
type: 2
minlevel: 1
maxlevel: 8
manacost: -1
recast_delay: 30
priority: 1
__________________
-Croup (the rogue)
Creator of Pandemic (PvP-Racewars)
Reply With Quote
  #2  
Old 07-16-2008, 09:32 AM
So_1337
Dragon
 
Join Date: May 2006
Location: Cincinnati, OH
Posts: 689
Default

I noticed this recently, and it's especially obvious among death-touching mobs like the Golems in Fear. I was even considering a work-around.

Currently, they cast it shortly after they're first aggro'd, and then you never see it again. On Live, it had a refresh timer of one minute, and they'd nuke whoever was at the top of their hate list. I know perl isn't the best solution for this, but I considered writing a script that would fire it off once a minute as it should, using a timer.

But if this recast delay and priority thing is straightened out, it'd be much better, for sure.
Reply With Quote
  #3  
Old 07-16-2008, 04:08 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Maybe it has something to do with the Spell Type setting for the NPC Spell Lists. I am wondering if only certain types will recognize the Recast Delay setting and some will ignore it. IMO, they should all follow the Recast Delay restriction. The ones I have tested so far are set to type 1, which is the Nuke setting. So, maybe the Nuke setting doesn't follow that restriction. Maybe I can try setting them to another type (maybe the DoT setting) and see if that makes any difference. Though, I still think that they should all follow the Recast Delay restriction.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #4  
Old 07-16-2008, 04:21 PM
moydock
Discordant
 
Join Date: Jun 2005
Posts: 286
Default

I don't think it affects it. I'm only testing lvl 5 npc's but my druids never nuke twice in a row as well as not healing. I've got 15 second delay on their nukes too. They'll cast bust of flame, and then firefist, or whatever that dot is, but never 2 burst of flame in a row.
__________________
-Croup (the rogue)
Creator of Pandemic (PvP-Racewars)
Reply With Quote
  #5  
Old 07-16-2008, 07:50 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

The proc chance might be why you aren't seeing them very close together. Try upping the proc chance up to 100% so that they should try to cast it every time it is available. Then, try setting your recast delay to something longer like 180 seconds and see if they cast it before that 3 minutes are up.

I will have to do more testing on it, but it is hard when I can only reset my server every now and then to test the changes, or it will effect my players too much if I reset alot.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #6  
Old 07-17-2008, 02:25 AM
moydock
Discordant
 
Join Date: Jun 2005
Posts: 286
Default

I tried setting the proc rate to 100 and oddly they don't seem to try to cast any quicker. Like, I attack them, and they wait awhile to cast the first nuke. Possibly because they need to wait the recast delay before casting the first spell.

Trust me though, I've sat in front of these things a lot. I would have seen one double cast by now.
I originally implemented the recast so that healers wouldn't chain heal themselves when they got low on health. And they don't anymore. I guess it's possible this has been broken in one of the somewhat recent updates.
__________________
-Croup (the rogue)
Creator of Pandemic (PvP-Racewars)
Reply With Quote
  #7  
Old 07-23-2008, 04:16 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Well, I am still trying to figure out why this is happening on my server. I was looking at my variables table and I have a setting for "ailevel", and it is set to 6 (which is how it came from the PEQ db), but I don't really know what that does. So far, it is the only thing I can think of that might be causing this issue. I am running the latest version of the emu (111 with some modified code additions, but nothing that I think would relate to this issue at all.

I was looking at the source and in npc.h, I see a public section that mentions ailevel, and has some recast delay info in there. So, I am wondering if maybe my ailevel is set wrong, and maybe setting it to 6 isn't enough for it to use recast delays...

Here is the code from the public section of npc.h that I am referring to (I highlighted a few things in RED cause I think they are involved in making the decision for recast delay settings):

Code:
class NPC : public Mob
{
public:
	static NPC* SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading = 0, Client* client = 0);
	static sint8 GetAILevel(bool iForceReRead = false);
	
	NPC(const NPCType* data, Spawn2* respawn, float x, float y, float z, float heading, bool IsCorpse = false);
	
	virtual ~NPC();

	virtual bool IsNPC() const { return true; }

	virtual bool Process();
	virtual void	AI_Init();
	virtual void	AI_Start(int32 iMoveDelay = 0);
	virtual void	AI_Stop();
	void			AI_DoMovement();
	bool			AI_AddNPCSpells(int32 iDBSpellsID);
	virtual bool	AI_EngagedCastCheck();
	virtual bool	AI_PursueCastCheck();
	virtual bool	AI_IdleCastCheck();
	virtual void	AI_Event_SpellCastFinished(bool iCastSucceeded, int8 slot);
	
	virtual void SetTarget(Mob* mob);
	virtual uint16 GetSkill(SkillType skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
/*  virtual void SetSkill(int in_skill_num, int8 in_skill_value) { // socket 12-29-01
        if (in_skill_num <= HIGHEST_SKILL) { skills[in_skill_num + 1] = in_skill_value; } }*/

	void CalcItemBonuses(StatBonuses *newbon);
	virtual void CalcBonuses();

	
#ifdef GUILDWARS
	int32	GetGuildLocationID() { return guildlocationid; }
#endif

	// neotokyo: added frenzy
	bool	Attack(Mob* other, int Hand = 13, bool = false);
	void	Damage(Mob* other, sint32 damage, int16 spell_id, SkillType attack_skill, bool avoidable = true, sint8 buffslot = -1, bool iBuffTic = false);
	void	Death(Mob* other, sint32 damage, int16 spell_id, SkillType attack_skill);
	bool	DatabaseCastAccepted(int spell_id);
	bool	IsFactionListAlly(uint32 other_faction);
	FACTION_VALUE CheckNPCFactionAlly(sint32 other_faction);
	FACTION_VALUE GetReverseFactionCon(Mob* iOther);

	void	GoToBind()	{ GMMove(org_x, org_y, org_z, org_heading); }
	void	Gate();

	void	GetPetState(SpellBuff_Struct *buffs, int32 *items, char *name);
	void	SetPetState(SpellBuff_Struct *buffs, int32 *items);
	void	InteractiveChat(int8 chan_num, int8 language, const char * message, const char* targetname,Mob* sender);
	void	TakenAction(int8 action,Mob* actiontaker);
	virtual void SpellProcess();
	virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);

	void	AddItem(const Item_Struct* item, int8 charges, int8 slot = 0);
	void	AddItem(int32 itemid, int8 charges, int8 slot = 0);
	void	AddLootTable();
/*
	void	NPCSpecialAttacks(const char* parse, int permtag);
	void	NPCDatabaseSpells(const char* parse);
	void	NPCUnharmSpell(int spell_id);
	void	CheckFriendlySpellStatus();

	void	CheckEnemySpellStatus();
	void	NPCHarmSpell(int target,int type);
	void    HateSummon();
*/	

	void	DescribeAggro(Client *towho, Mob *mob, bool verbose);
	void    RemoveItem(uint16 item_id, int16 quantity = 0, int16 slot = 0);
//	bool	AddNPCSpells(int32 iDBSpellsID, AISpells_Struct* AIspells);
//	void	RemoveItem(uint16 item_id);
	void	ClearItemList();
	ServerLootItem_Struct*	GetItem(int slot_id);
	void	AddCash(int16 in_copper, int16 in_silver, int16 in_gold, int16 in_platinum);
	void	AddCash();
	void	RemoveCash();
	void	QueryLoot(Client* to);
	int32	CountLoot();
	void	DumpLoot(int32 npcdump_index, ZSDump_NPC_Loot* npclootdump, int32* NPCLootindex);
	inline int32	GetLoottableID()	const { return loottable_id; }
//	void	SetPetType(int16 in_type)	{ typeofpet = in_type; } // put this here because only NPCs can be anything but charmed pets

	inline uint32	GetCopper()		const { return copper; }
	inline uint32	GetSilver()		const { return silver; }
	inline uint32	GetGold()		const { return gold; }
	inline uint32	GetPlatinum()	const { return platinum; }

	inline void	SetCopper(uint32 amt)		{ copper = amt; }
	inline void	SetSilver(uint32 amt)		{ silver = amt; }
	inline void	SetGold(uint32 amt)			{ gold = amt; }
	inline void	SetPlatinum(uint32 amt)		{ platinum = amt; }



	void SetGrid(int32 grid_){ grid=grid_; }
	void SetSp2(int32 sg2){ spawn_group=sg2; }
	void SetWaypointMax(int16 wp_){ wp_m=wp_; }

	int16 GetWaypointMax() const { return wp_m; }
	int32 GetGrid() const { return grid; }
	int32 GetSp2() const { return spawn_group; }

	uint32	MerchantType;
	void	Depop(bool StartSpawnTimer = true);
	void	Stun(int duration);
	void	UnStun();
	
	inline void SignalNPC(int _signal_id) { signaled = true; signal_id = _signal_id; }
	
	inline sint32	GetNPCFactionID()	const { return npc_faction_id; }
	inline sint32			GetPrimaryFaction()	const { return primary_faction; }
	sint32	GetNPCHate(Mob* in_ent)  {return hate_list.GetEntHate(in_ent);}
    bool    IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);}

	void	SetNPCFactionID(sint32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }

	float   org_x, org_y, org_z, org_heading;
	
	int16	GetMaxDMG() const {return max_dmg;}
	bool	IsAnimal() const { return(bodytype == BT_Animal); }
	int16   GetPetSpellID() const {return pet_spell_id;}
	void    SetPetSpellID(int16 amt) {pet_spell_id = amt;}
	int32	GetMaxDamage(int8 tlevel);
	void    SetTaunting(bool tog) {taunting = tog;}
	void	PickPocket(Client* thief);
	void	StartSwarmTimer(int32 duration) { swarm_timer.Start(duration); }
	void	AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, sint8 charges, bool equipit, bool wearchange = false);
	void	DoClassAttacks(Mob *target);
	void	CheckSignal();
	
	//waypoint crap
	int		GetMaxWp() const { return max_wp; }
	void				DisplayWaypointInfo(Client *to);
	void				CalculateNewWaypoint();
//	int8				CalculateHeadingToNextWaypoint();
//	float				CalculateDistanceToNextWaypoint();
	void				AssignWaypoints(int32 grid);
	void				SetWaypointPause();
	void				UpdateWaypoint(int wp_index);
	// quest wandering commands
	void				StopWandering();
	void				ResumeWandering();
	void				PauseWandering(int pausetime);
	void				MoveTo(float mtx, float mty, float mtz);
	
	int32				GetEquipment(int8 material_slot) const;	// returns item id
	sint32				GetEquipmentMaterial(int8 material_slot) const;
	
	void				NextGuardPosition();
	void				SaveGuardSpot(bool iClearGuardSpot = false);
	inline bool			IsGuarding() const { return(guard_heading != 0); }
/*	void				SaveSpawnSpot();
	inline const float	GetSpawnX() const { return spawn_x; }
	inline const float	GetSpawnY() const { return spawn_y; }
	inline const float	GetSpawnZ() const { return spawn_z; }
	inline const float	GetSpawnHeading() const { return spawn_heading; }
	*/
	void				AI_SetRoambox(float iDist, float iRoamDist, int32 iDelay = 2500);
	void				AI_SetRoambox(float iDist, float iMaxX, float iMinX, float iMaxY, float iMinY, int32 iDelay = 2500);
	
	
	inline bool WillAggroNPCs() const { return(npc_aggro); }
	
	inline void GiveNPCTypeData(NPCType *ours) { NPCTypedata_ours = ours; }
	inline const int32 GetNPCSpellsID()	const { return npc_spells_id; }
	
	ItemList	itemlist; //kathgar - why is this public?  Doing other things or I would check the code
	
	NPCProximity* proximity;

	Spawn2*	respawn2;

	AA_SwarmPetInfo *GetSwarmInfo() { return (swarmInfoPtr); }
	void SetSwarmInfo(AA_SwarmPetInfo *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; }

	sint32	GetAccuracyRating() { return (accuracy_rating); }
	void	SetAccuracyRating(sint32 d) { accuracy_rating = d;}

protected:
	
	const NPCType*	NPCTypedata;
	NPCType*	NPCTypedata_ours;	//special case for npcs with uniquely created data.

	friend class EntityList;
	list<struct NPCFaction*> faction_list;
	uint32	copper;
	uint32	silver;
	uint32	gold;
	uint32	platinum;
	int32   grid;
	int32   spawn_group;
	int16	wp_m;

	sint32	npc_faction_id;
	sint32	primary_faction;
	
	Timer	attacked_timer;		//running while we are being attacked (damaged)
	Timer	combat_event_timer;	//running while we are engaged in offensive or defensive combat activities
    Timer	swarm_timer;
    Timer	classattack_timer;
	Timer	knightattack_timer;
    Timer	assist_timer;		//ask for help from nearby mobs
	Timer	global_position_update_timer;

	bool	attack_event;	//true if we have fired an EVENT_ATTACK and our attacked timer has not gone off
	bool	combat_event;	//true if we have fired an EVENT_COMBAT and our combat activity timer has not gone off

//	int8	position;	// 0 - Standing, 1 - Sitting, 2 - Crouching, 4 - Looting
    Timer	sendhpupdate_timer;
	Timer	enraged_timer;

	int32	npc_spells_id;
	struct AISpells_Struct {
		int16	type;			// 0 = never, must be one (and only one) of the defined values
		uint16	spellid;		// <= 0 = no spell
		sint16	manacost;		// -1 = use spdat, -2 = no cast time
		int32	time_cancast;	// when we can cast this spell next
		sint32	recast_delay;
		sint16	priority;
	};
	int8	casting_spell_AIindex;
	Timer*	AIautocastspell_timer;
	int32*	pDontCastBefore_casting_spell;
	AISpells_Struct	AIspells[MAX_AISPELLS]; // expected to be pre-sorted, best at low index
	void AddSpellToNPCList(AISpells_Struct* AIspells, sint16 iPriority, sint16 iSpellID, uint16 iType, sint16 iManaCost, sint32 iRecastDelay);
	bool AICastSpell(Mob* tar, int8 iChance, int16 iSpellTypes);
	void AIDoSpellCast(int8 i, Mob* tar, sint32 mana_cost, int32* oDontDoAgainBefore = 0);
	
	
	int16	max_dmg;
	int16	min_dmg;
	sint32	accuracy_rating;
	
	//pet crap:
	int16	pet_spell_id;
	bool	taunting;
    Timer	taunt_timer;		//for pet taunting
	
	bool npc_aggro;
	
	int		signal_id;
	bool	signaled;	// used by quest signal() command
	
	//waypoint crap:
	//MyList <wplist> Waypoints;
	vector<wplist> Waypoints;
	void _ClearWaypints();
	int		max_wp;
	int		save_wp;
    float guard_x, guard_y, guard_z, guard_heading;
//    float spawn_x, spawn_y, spawn_z, spawn_heading;
	float roambox_max_x;
	float roambox_max_y;
	float roambox_min_x;
	float roambox_min_y;
	float roambox_distance;
	float roambox_movingto_x;
	float roambox_movingto_y;
	int32 roambox_delay;
	
	int16   skills[HIGHEST_SKILL+1];
	int32   equipment[MAX_MATERIALS];	//this is an array of item IDs
	int16	d_meele_texture1;		//this is an item Material value
	int16	d_meele_texture2;		//this is an item Material value (offhand)

	AA_SwarmPetInfo *swarmInfoPtr;
This issue is hanging me up from adding disciplines to NPCs to make some interesting encounters. I know I could probably do most of it via quests if I wanted, but these are mainly for my trash mobs. I am trying to make trash mob fights a little more dynamic.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 03:14 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3