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

07-15-2008, 10:39 PM
|
Discordant
|
|
Join Date: Jun 2005
Posts: 286
|
|
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)
|

07-16-2008, 09:32 AM
|
Dragon
|
|
Join Date: May 2006
Location: Cincinnati, OH
Posts: 689
|
|
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.
|

07-16-2008, 04:08 PM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
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.
|

07-16-2008, 04:21 PM
|
Discordant
|
|
Join Date: Jun 2005
Posts: 286
|
|
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)
|

07-16-2008, 07:50 PM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
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.
|

07-17-2008, 02:25 AM
|
Discordant
|
|
Join Date: Jun 2005
Posts: 286
|
|
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)
|
 |
|
 |

07-23-2008, 04:16 AM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
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.
|
 |
|
 |
Thread Tools |
|
Display Modes |
Hybrid Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 03:14 AM.
|
|
 |
|
 |
|
|
|
 |
|
 |
|
 |