//-1 will return equipping feature block //otherwise returns the n'th feature block EffectQueue *Item::GetEffectBlock(Scriptable *self, const Point &pos, int usage, ieDwordSigned invslot, ieDword pro) const { Effect *features; int count; if (usage>=ExtHeaderCount) { return NULL; } if (usage>=0) { features = ext_headers[usage].features; count = ext_headers[usage].FeatureCount; } else { features = equipping_features; count = EquippingFeatureCount; } EffectQueue *fxqueue = new EffectQueue(); for (int i=0;i<count;i++) { Effect *fx = features+i; fx->InventorySlot = invslot; fx->CasterLevel = ITEM_CASTERLEVEL; //items all have casterlevel 10 if (usage >= 0) { //this is not coming from the item header, but from the recharge flags fx->SourceFlags = ext_headers[usage].RechargeFlags; } else { fx->SourceFlags = 0; } if (fx->Target != FX_TARGET_SELF) { fx->Projectile = pro; fxqueue->AddEffect( fx ); } else { Actor *target = (self->Type==ST_ACTOR)?(Actor *) self:NULL; fx->Projectile = 0; fx->PosX=pos.x; fx->PosY=pos.y; if (target) { core->ApplyEffect(fx, target, self); } } } //adding a pulse effect for weapons (PST) //if it is an equipping effect block if ((usage==-1) && (WieldColor!=0xffff)) { if (Flags&IE_ITEM_PULSATING) { Effect *tmp = BuildGlowEffect(WieldColor); if (tmp) { tmp->InventorySlot = invslot; tmp->Projectile=pro; fxqueue->AddEffect( tmp ); delete tmp; } } } return fxqueue; }
EffectQueue *Spell::GetEffectBlock(Scriptable *self, const Point &pos, int block_index, int level, ieDword pro) const { bool pst_hostile = false; Effect *features; int count; //iwd2 has this hack if (block_index>=0) { if (Flags & SF_SIMPLIFIED_DURATION) { features = ext_headers[0].features; count = ext_headers[0].FeatureCount; } else { features = ext_headers[block_index].features; count = ext_headers[block_index].FeatureCount; if (pstflags && !(ext_headers[block_index].Hostile&4)) { pst_hostile = true; } } } else { features = casting_features; count = CastingFeatureCount; } EffectQueue *fxqueue = new EffectQueue(); EffectQueue *selfqueue = NULL; for (int i=0;i<count;i++) { Effect *fx = features+i; if ((Flags & SF_SIMPLIFIED_DURATION) && (block_index>=0)) { //hack the effect according to Level //fxqueue->AddEffect will copy the effect, //so we don't risk any overwriting if (EffectQueue::HasDuration(features+i)) { fx->Duration = (TimePerLevel*block_index+TimeConstant)*core->Time.round_sec; } } //fill these for completeness, inventoryslot is a good way //to discern a spell from an item effect fx->InventorySlot = 0xffff; //the hostile flag is used to determine if this was an attack fx->SourceFlags = Flags; //pst spells contain a friendly flag in the spell header if (pst_hostile) { fx->SourceFlags|=SF_HOSTILE; } fx->CasterLevel = level; fx->SpellLevel = SpellLevel; // apply the stat-based spell duration modifier if (self->Type == ST_ACTOR) { Actor *caster = (Actor *) self; if (caster->Modified[IE_SPELLDURATIONMODMAGE] && SpellType == IE_SPL_WIZARD) { fx->Duration = (fx->Duration * caster->Modified[IE_SPELLDURATIONMODMAGE]) / 100; } else if (caster->Modified[IE_SPELLDURATIONMODPRIEST] && SpellType == IE_SPL_PRIEST) { fx->Duration = (fx->Duration * caster->Modified[IE_SPELLDURATIONMODPRIEST]) / 100; } //evaluate spell focus feats //TODO: the usual problem: which saving throw is better? Easy fix in the data file. if (fx->PrimaryType<(ieDword) schoolcount) { ieDword stat = spellfocus[fx->PrimaryType].stat; if (stat>0) { switch (caster->Modified[stat]) { case 0: break; case 1: fx->SavingThrowBonus += spellfocus[fx->PrimaryType].val1; break; default: fx->SavingThrowBonus += spellfocus[fx->PrimaryType].val2; break; } } } } if (fx->Target != FX_TARGET_PRESET && EffectQueue::OverrideTarget(fx)) { fx->Target = FX_TARGET_PRESET; } if (fx->Target != FX_TARGET_SELF) { fx->Projectile = pro; fxqueue->AddEffect( fx ); } else { fx->Projectile = 0; fx->PosX=pos.x; fx->PosY=pos.y; if (!selfqueue) { selfqueue = new EffectQueue(); } // effects should be able to affect non living targets //This is done by NULL target, the position should be enough //to tell which non-actor object is affected selfqueue->AddEffect( fx ); } } if (selfqueue) { Actor *target = (self->Type==ST_ACTOR)?(Actor *) self:NULL; core->ApplyEffectQueue(selfqueue, target, self); delete selfqueue; } return fxqueue; }